Second version of !33, taking Zeb's suggestions.
The refactoring allowed to encompass all remaining features of the patch series in these 4 patches.
The remaining patches (PART 3/3) just contain additional tests: https://gitlab.winehq.org/fcasas/vkd3d/-/commits/complex_broadcasts_4/
-- v2: vkd3d-shader/hlsl: Support explicit cast between component-wise compatible types. vkd3d-shader/hlsl: Support implicit casts between component-wise equal types. vkd3d-shader/hlsl: Remove incorrect criteria for accepting implicit casts. vkd3d-shader/hlsl: Handle complex types in add_cast(). tests: Add additional tests for implicit casts that should fail. vkd3d-shader/hlsl: Rename "t1" and "t2" arguments as "src" and "dst".
From: Francisco Casas fcasas@codeweavers.com
--- libs/vkd3d-shader/hlsl.y | 110 +++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 55 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 62d86b9d..cc0a40ff 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -153,121 +153,121 @@ static bool convertible_data_type(struct hlsl_type *type) return type->type != HLSL_CLASS_OBJECT; }
-static bool compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) +static bool compatible_data_types(struct hlsl_type *src, struct hlsl_type *dst) { - if (!convertible_data_type(t1) || !convertible_data_type(t2)) + if (!convertible_data_type(src) || !convertible_data_type(dst)) return false;
- if (t1->type <= HLSL_CLASS_LAST_NUMERIC) + if (src->type <= HLSL_CLASS_LAST_NUMERIC) { /* Scalar vars can be cast to pretty much everything */ - if (t1->dimx == 1 && t1->dimy == 1) + if (src->dimx == 1 && src->dimy == 1) return true;
- if (t1->type == HLSL_CLASS_VECTOR && t2->type == HLSL_CLASS_VECTOR) - return t1->dimx >= t2->dimx; + if (src->type == HLSL_CLASS_VECTOR && dst->type == HLSL_CLASS_VECTOR) + return src->dimx >= dst->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) + if (dst->type <= HLSL_CLASS_LAST_NUMERIC && dst->dimx == 1 && dst->dimy == 1) return true;
- if (t1->type == HLSL_CLASS_ARRAY) + if (src->type == HLSL_CLASS_ARRAY) { - if (hlsl_types_are_equal(t1->e.array.type, t2)) + if (hlsl_types_are_equal(src->e.array.type, dst)) /* e.g. float4[3] to float4 is allowed */ return true;
- if (t2->type == HLSL_CLASS_ARRAY || t2->type == HLSL_CLASS_STRUCT) - return hlsl_type_component_count(t1) >= hlsl_type_component_count(t2); + if (dst->type == HLSL_CLASS_ARRAY || dst->type == HLSL_CLASS_STRUCT) + return hlsl_type_component_count(src) >= hlsl_type_component_count(dst); else - return hlsl_type_component_count(t1) == hlsl_type_component_count(t2); + return hlsl_type_component_count(src) == hlsl_type_component_count(dst); }
- if (t1->type == HLSL_CLASS_STRUCT) - return hlsl_type_component_count(t1) >= hlsl_type_component_count(t2); + if (src->type == HLSL_CLASS_STRUCT) + return hlsl_type_component_count(src) >= hlsl_type_component_count(dst);
- if (t2->type == HLSL_CLASS_ARRAY || t2->type == HLSL_CLASS_STRUCT) - return hlsl_type_component_count(t1) == hlsl_type_component_count(t2); + if (dst->type == HLSL_CLASS_ARRAY || dst->type == HLSL_CLASS_STRUCT) + return hlsl_type_component_count(src) == hlsl_type_component_count(dst);
- if (t1->type == HLSL_CLASS_MATRIX || t2->type == HLSL_CLASS_MATRIX) + if (src->type == HLSL_CLASS_MATRIX || dst->type == HLSL_CLASS_MATRIX) { - if (t1->type == HLSL_CLASS_MATRIX && t2->type == HLSL_CLASS_MATRIX && t1->dimx >= t2->dimx && t1->dimy >= t2->dimy) + if (src->type == HLSL_CLASS_MATRIX && dst->type == HLSL_CLASS_MATRIX && src->dimx >= dst->dimx && src->dimy >= dst->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)) + if ((src->type == HLSL_CLASS_VECTOR || dst->type == HLSL_CLASS_VECTOR) + && hlsl_type_component_count(src) == hlsl_type_component_count(dst)) return true; return false; }
- if (hlsl_type_component_count(t1) >= hlsl_type_component_count(t2)) + if (hlsl_type_component_count(src) >= hlsl_type_component_count(dst)) return true; return false; }
-static bool implicit_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) +static bool implicit_compatible_data_types(struct hlsl_type *src, struct hlsl_type *dst) { - if (!convertible_data_type(t1) || !convertible_data_type(t2)) + if (!convertible_data_type(src) || !convertible_data_type(dst)) return false;
- if (t1->type <= HLSL_CLASS_LAST_NUMERIC) + if (src->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) + if (src->dimx == 1 && src->dimy == 1 && dst->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) + if (dst->dimx == 1 && dst->dimy == 1 && dst->type <= HLSL_CLASS_LAST_NUMERIC) return true; }
- if (t1->type == HLSL_CLASS_ARRAY && t2->type == HLSL_CLASS_ARRAY) + if (src->type == HLSL_CLASS_ARRAY && dst->type == HLSL_CLASS_ARRAY) { - return hlsl_type_component_count(t1) == hlsl_type_component_count(t2); + return hlsl_type_component_count(src) == hlsl_type_component_count(dst); }
- if ((t1->type == HLSL_CLASS_ARRAY && t2->type <= HLSL_CLASS_LAST_NUMERIC) - || (t1->type <= HLSL_CLASS_LAST_NUMERIC && t2->type == HLSL_CLASS_ARRAY)) + if ((src->type == HLSL_CLASS_ARRAY && dst->type <= HLSL_CLASS_LAST_NUMERIC) + || (src->type <= HLSL_CLASS_LAST_NUMERIC && dst->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)) + if (src->type == HLSL_CLASS_ARRAY && hlsl_types_are_equal(src->e.array.type, dst)) return true; - if (hlsl_type_component_count(t1) == hlsl_type_component_count(t2)) + if (hlsl_type_component_count(src) == hlsl_type_component_count(dst)) return true; return false; }
- if (t1->type <= HLSL_CLASS_VECTOR && t2->type <= HLSL_CLASS_VECTOR) + if (src->type <= HLSL_CLASS_VECTOR && dst->type <= HLSL_CLASS_VECTOR) { - if (t1->dimx >= t2->dimx) + if (src->dimx >= dst->dimx) return true; return false; }
- if (t1->type == HLSL_CLASS_MATRIX || t2->type == HLSL_CLASS_MATRIX) + if (src->type == HLSL_CLASS_MATRIX || dst->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 (src->type == HLSL_CLASS_MATRIX && dst->type == HLSL_CLASS_MATRIX) + return src->dimx >= dst->dimx && src->dimy >= dst->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 (src->type == HLSL_CLASS_VECTOR || dst->type == HLSL_CLASS_VECTOR) { - if (hlsl_type_component_count(t1) == hlsl_type_component_count(t2)) + if (hlsl_type_component_count(src) == hlsl_type_component_count(dst)) 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); + if ((src->type == HLSL_CLASS_VECTOR || src->dimx == 1 || src->dimy == 1) && + (dst->type == HLSL_CLASS_VECTOR || dst->dimx == 1 || dst->dimy == 1)) + return hlsl_type_component_count(src) >= hlsl_type_component_count(dst); }
return false; }
- if (t1->type == HLSL_CLASS_STRUCT && t2->type == HLSL_CLASS_STRUCT) - return hlsl_types_are_equal(t1, t2); + if (src->type == HLSL_CLASS_STRUCT && dst->type == HLSL_CLASS_STRUCT) + return hlsl_types_are_equal(src, dst);
return false; } @@ -1167,34 +1167,34 @@ static unsigned int evaluate_array_dimension(struct hlsl_ir_node *node) } }
-static bool expr_compatible_data_types(struct hlsl_type *t1, struct hlsl_type *t2) +static bool expr_compatible_data_types(struct hlsl_type *src, struct hlsl_type *dst) { - if (t1->base_type > HLSL_TYPE_LAST_SCALAR || t2->base_type > HLSL_TYPE_LAST_SCALAR) + if (src->base_type > HLSL_TYPE_LAST_SCALAR || dst->base_type > HLSL_TYPE_LAST_SCALAR) return false;
/* Scalar vars can be converted to pretty much everything */ - if ((t1->dimx == 1 && t1->dimy == 1) || (t2->dimx == 1 && t2->dimy == 1)) + if ((src->dimx == 1 && src->dimy == 1) || (dst->dimx == 1 && dst->dimy == 1)) return true;
- if (t1->type == HLSL_CLASS_VECTOR && t2->type == HLSL_CLASS_VECTOR) + if (src->type == HLSL_CLASS_VECTOR && dst->type == HLSL_CLASS_VECTOR) return true;
- if (t1->type == HLSL_CLASS_MATRIX || t2->type == HLSL_CLASS_MATRIX) + if (src->type == HLSL_CLASS_MATRIX || dst->type == HLSL_CLASS_MATRIX) { /* Matrix-vector conversion is apparently allowed if either they have the same components count or the matrix is nx1 or 1xn */ - if (t1->type == HLSL_CLASS_VECTOR || t2->type == HLSL_CLASS_VECTOR) + if (src->type == HLSL_CLASS_VECTOR || dst->type == HLSL_CLASS_VECTOR) { - if (hlsl_type_component_count(t1) == hlsl_type_component_count(t2)) + if (hlsl_type_component_count(src) == hlsl_type_component_count(dst)) return true;
- return (t1->type == HLSL_CLASS_MATRIX && (t1->dimx == 1 || t1->dimy == 1)) - || (t2->type == HLSL_CLASS_MATRIX && (t2->dimx == 1 || t2->dimy == 1)); + return (src->type == HLSL_CLASS_MATRIX && (src->dimx == 1 || src->dimy == 1)) + || (dst->type == HLSL_CLASS_MATRIX && (dst->dimx == 1 || dst->dimy == 1)); }
/* Both matrices */ - if ((t1->dimx >= t2->dimx && t1->dimy >= t2->dimy) - || (t1->dimx <= t2->dimx && t1->dimy <= t2->dimy)) + if ((src->dimx >= dst->dimx && src->dimy >= dst->dimy) + || (src->dimx <= dst->dimx && src->dimy <= dst->dimy)) return true; }
From: Francisco Casas fcasas@codeweavers.com
--- tests/cast-componentwise-equal.shader_test | 90 ++++++++++++++++++++++ 1 file changed, 90 insertions(+)
diff --git a/tests/cast-componentwise-equal.shader_test b/tests/cast-componentwise-equal.shader_test index ac329112..8a98b45c 100644 --- a/tests/cast-componentwise-equal.shader_test +++ b/tests/cast-componentwise-equal.shader_test @@ -224,3 +224,93 @@ float4 main() : sv_target b = a; return b.bb; } + + +[pixel shader fail todo] +float main() : SV_TARGET +{ + float arr[3] = {1, 2, 3}; + float v; + + v = arr; + return 0; +} + + +[pixel shader fail todo] +float main() : SV_TARGET +{ + float2 arr[3] = {1, 2, 3, 4, 5, 6}; + float2 vec; + + vec = arr; + return 0; +} + + +[pixel shader fail todo] +float4 main() : SV_TARGET +{ + int arr1[4] = {1, 2, 3, 4}; + float arr2[4]; + + arr2 = arr1; + return 0; +} + + +[pixel shader fail] +float4 main() : SV_TARGET +{ + float2x2 mat = {1, 2, 3, 4}; + float3 vec; + + vec = mat; + return 0; +} + + +[pixel shader fail todo] +float4 main() : SV_TARGET +{ + float4 f = {1, 2, 3, 4}; + float arr[4]; + + arr = f; + return 0; +} + + +[pixel shader fail todo] +float4 main() : SV_TARGET +{ + float arr[4] = {1, 2, 3, 4}; + float4 f; + + f = arr; + return 0; +} + + +[pixel shader fail] +float4 main() : SV_TARGET +{ + float3x2 mat1 = {1, 2, 3, 4, 5, 6}; + float2x3 mat2; + + mat2 = mat1; + return 0; +} + + +[pixel shader fail] +struct apple { + float aa; +}; + +float4 main() : SV_TARGET +{ + struct apple a = 3.0; + + return 0; +}
From: Francisco Casas fcasas@codeweavers.com
--- libs/vkd3d-shader/hlsl.y | 16 ---------------- tests/cast-componentwise-equal.shader_test | 10 +++++----- 2 files changed, 5 insertions(+), 21 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 184a8613..d0bbee9e 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -222,22 +222,6 @@ static bool implicit_compatible_data_types(struct hlsl_type *src, struct hlsl_ty return true; }
- if (src->type == HLSL_CLASS_ARRAY && dst->type == HLSL_CLASS_ARRAY) - { - return hlsl_type_component_count(src) == hlsl_type_component_count(dst); - } - - if ((src->type == HLSL_CLASS_ARRAY && dst->type <= HLSL_CLASS_LAST_NUMERIC) - || (src->type <= HLSL_CLASS_LAST_NUMERIC && dst->type == HLSL_CLASS_ARRAY)) - { - /* e.g. float4[3] to float4 is allowed */ - if (src->type == HLSL_CLASS_ARRAY && hlsl_types_are_equal(src->e.array.type, dst)) - return true; - if (hlsl_type_component_count(src) == hlsl_type_component_count(dst)) - return true; - return false; - } - if (src->type <= HLSL_CLASS_VECTOR && dst->type <= HLSL_CLASS_VECTOR) { if (src->dimx >= dst->dimx) diff --git a/tests/cast-componentwise-equal.shader_test b/tests/cast-componentwise-equal.shader_test index 8a98b45c..30c26c63 100644 --- a/tests/cast-componentwise-equal.shader_test +++ b/tests/cast-componentwise-equal.shader_test @@ -226,7 +226,7 @@ float4 main() : sv_target }
-[pixel shader fail todo] +[pixel shader fail] float main() : SV_TARGET { float arr[3] = {1, 2, 3}; @@ -237,7 +237,7 @@ float main() : SV_TARGET }
-[pixel shader fail todo] +[pixel shader fail] float main() : SV_TARGET { float2 arr[3] = {1, 2, 3, 4, 5, 6}; @@ -248,7 +248,7 @@ float main() : SV_TARGET }
-[pixel shader fail todo] +[pixel shader fail] float4 main() : SV_TARGET { int arr1[4] = {1, 2, 3, 4}; @@ -270,7 +270,7 @@ float4 main() : SV_TARGET }
-[pixel shader fail todo] +[pixel shader fail] float4 main() : SV_TARGET { float4 f = {1, 2, 3, 4}; @@ -281,7 +281,7 @@ float4 main() : SV_TARGET }
-[pixel shader fail todo] +[pixel shader fail] float4 main() : SV_TARGET { float arr[4] = {1, 2, 3, 4};
From: Francisco Casas fcasas@codeweavers.com
This extends the support of this function, whether doing broadcasts or component-wise casts, to struct and array types.
---
In the following patches, compatible_data_types() and implicit_compatible_data_types() are improved so that: * Casts that should be allowed actually reach add_cast(). * Casts that shouldn't be allowed because of special conditions (besides component count), e.g. matrix to matrix, don't reach add_cast(). --- libs/vkd3d-shader/hlsl.y | 40 +++++++++---------- tests/cast-broadcast.shader_test | 4 +- .../cast-componentwise-compatible.shader_test | 20 +++++----- 3 files changed, 32 insertions(+), 32 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index cc0a40ff..184a8613 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -284,18 +284,21 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs, if (hlsl_types_are_equal(src_type, dst_type)) return node;
- 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) + if (src_type->type > HLSL_CLASS_VECTOR || dst_type->type > HLSL_CLASS_VECTOR) { + unsigned int src_comp_count = hlsl_type_component_count(src_type); + unsigned int dst_comp_count = hlsl_type_component_count(dst_type); struct hlsl_deref var_deref; + bool broadcast, matrix_cast; struct hlsl_ir_load *load; struct hlsl_ir_var *var; unsigned int dst_idx; - bool broadcast;
- broadcast = src_type->dimx == 1 && src_type->dimy == 1; - assert(dst_type->dimx * dst_type->dimy <= src_type->dimx * src_type->dimy || broadcast); - if (src_type->type == HLSL_CLASS_MATRIX && dst_type->type == HLSL_CLASS_MATRIX && !broadcast) + broadcast = src_type->type <= HLSL_CLASS_LAST_NUMERIC && src_type->dimx == 1 && src_type->dimy == 1; + matrix_cast = !broadcast && dst_comp_count != src_comp_count + && src_type->type == HLSL_CLASS_MATRIX && dst_type->type == HLSL_CLASS_MATRIX; + assert(src_comp_count >= dst_comp_count || broadcast); + if (matrix_cast) { assert(dst_type->dimx <= src_type->dimx); assert(dst_type->dimy <= src_type->dimy); @@ -305,9 +308,9 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs, return NULL; hlsl_init_simple_deref_from_var(&var_deref, var);
- for (dst_idx = 0; dst_idx < dst_type->dimx * dst_type->dimy; ++dst_idx) + for (dst_idx = 0; dst_idx < dst_comp_count; ++dst_idx) { - struct hlsl_type *dst_scalar_type; + struct hlsl_type *dst_comp_type; struct hlsl_ir_store *store; struct hlsl_block block; unsigned int src_idx; @@ -316,26 +319,23 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs, { src_idx = 0; } - else + else if (matrix_cast) { - if (src_type->type == HLSL_CLASS_MATRIX && dst_type->type == HLSL_CLASS_MATRIX) - { - unsigned int x = dst_idx % dst_type->dimx, y = dst_idx / dst_type->dimx; + unsigned int x = dst_idx % dst_type->dimx, y = dst_idx / dst_type->dimx;
- src_idx = y * src_type->dimx + x; - } - else - { - src_idx = dst_idx; - } + src_idx = y * src_type->dimx + x; + } + else + { + src_idx = dst_idx; }
- dst_scalar_type = hlsl_type_get_component_type(ctx, dst_type, dst_idx); + dst_comp_type = hlsl_type_get_component_type(ctx, dst_type, dst_idx);
if (!(load = add_load_component(ctx, instrs, node, src_idx, loc))) return NULL;
- if (!(cast = hlsl_new_cast(ctx, &load->node, dst_scalar_type, loc))) + if (!(cast = hlsl_new_cast(ctx, &load->node, dst_comp_type, loc))) return NULL; list_add_tail(instrs, &cast->node.entry);
diff --git a/tests/cast-broadcast.shader_test b/tests/cast-broadcast.shader_test index e21e65b0..d8571fc8 100644 --- a/tests/cast-broadcast.shader_test +++ b/tests/cast-broadcast.shader_test @@ -19,8 +19,8 @@ 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)
[pixel shader fail] 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]
From: Francisco Casas fcasas@codeweavers.com
--- libs/vkd3d-shader/hlsl.y | 79 +++++++++++++--------- tests/cast-componentwise-equal.shader_test | 16 ++--- 2 files changed, 55 insertions(+), 40 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index d0bbee9e..3cc00f95 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -153,6 +153,27 @@ static bool convertible_data_type(struct hlsl_type *type) return type->type != HLSL_CLASS_OBJECT; }
+static bool hlsl_types_are_componentwise_equal(struct hlsl_ctx *ctx, struct hlsl_type *src, + struct hlsl_type *dst) +{ + unsigned int k, count = hlsl_type_component_count(src); + + if (count != hlsl_type_component_count(dst)) + return false; + + for (k = 0; k < count; ++k) + { + struct hlsl_type *src_comp_type, *dst_comp_type; + + src_comp_type = hlsl_type_get_component_type(ctx, src, k); + dst_comp_type = hlsl_type_get_component_type(ctx, dst, k); + + if (!hlsl_types_are_equal(src_comp_type, dst_comp_type)) + return false; + } + return true; +} + static bool compatible_data_types(struct hlsl_type *src, struct hlsl_type *dst) { if (!convertible_data_type(src) || !convertible_data_type(dst)) @@ -207,53 +228,47 @@ static bool compatible_data_types(struct hlsl_type *src, struct hlsl_type *dst) return false; }
-static bool implicit_compatible_data_types(struct hlsl_type *src, struct hlsl_type *dst) +static bool implicit_compatible_data_types(struct hlsl_ctx *ctx, struct hlsl_type *src, struct hlsl_type *dst) { - if (!convertible_data_type(src) || !convertible_data_type(dst)) + if ((src->type <= HLSL_CLASS_LAST_NUMERIC) != (dst->type <= HLSL_CLASS_LAST_NUMERIC)) return false;
if (src->type <= HLSL_CLASS_LAST_NUMERIC) { /* Scalar vars can be converted to any other numeric data type */ - if (src->dimx == 1 && src->dimy == 1 && dst->type <= HLSL_CLASS_LAST_NUMERIC) + if (src->dimx == 1 && src->dimy == 1) return true; /* The other way around is true too */ - if (dst->dimx == 1 && dst->dimy == 1 && dst->type <= HLSL_CLASS_LAST_NUMERIC) + if (dst->dimx == 1 && dst->dimy == 1) return true; - }
- if (src->type <= HLSL_CLASS_VECTOR && dst->type <= HLSL_CLASS_VECTOR) - { - if (src->dimx >= dst->dimx) - return true; - return false; - } + if (src->type == HLSL_CLASS_MATRIX || dst->type == HLSL_CLASS_MATRIX) + { + if (src->type == HLSL_CLASS_MATRIX && dst->type == HLSL_CLASS_MATRIX) + return src->dimx >= dst->dimx && src->dimy >= dst->dimy;
- if (src->type == HLSL_CLASS_MATRIX || dst->type == HLSL_CLASS_MATRIX) - { - if (src->type == HLSL_CLASS_MATRIX && dst->type == HLSL_CLASS_MATRIX) - return src->dimx >= dst->dimx && src->dimy >= dst->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 (src->type == HLSL_CLASS_VECTOR || dst->type == HLSL_CLASS_VECTOR) + { + if (hlsl_type_component_count(src) == hlsl_type_component_count(dst)) + return true;
- /* 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 (src->type == HLSL_CLASS_VECTOR || dst->type == HLSL_CLASS_VECTOR) - { - if (hlsl_type_component_count(src) == hlsl_type_component_count(dst)) - return true; + if ((src->type == HLSL_CLASS_VECTOR || src->dimx == 1 || src->dimy == 1) && + (dst->type == HLSL_CLASS_VECTOR || dst->dimx == 1 || dst->dimy == 1)) + return hlsl_type_component_count(src) >= hlsl_type_component_count(dst); + }
- if ((src->type == HLSL_CLASS_VECTOR || src->dimx == 1 || src->dimy == 1) && - (dst->type == HLSL_CLASS_VECTOR || dst->dimx == 1 || dst->dimy == 1)) - return hlsl_type_component_count(src) >= hlsl_type_component_count(dst); + return false; + } + else + { + return src->dimx >= dst->dimx; } - - return false; }
- if (src->type == HLSL_CLASS_STRUCT && dst->type == HLSL_CLASS_STRUCT) - return hlsl_types_are_equal(src, dst); - - return false; + return hlsl_types_are_componentwise_equal(ctx, src, dst); }
static struct hlsl_ir_load *add_load_component(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *var_instr, @@ -351,7 +366,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 30c26c63..4c85b9ed 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]
From: Francisco Casas fcasas@codeweavers.com
--- libs/vkd3d-shader/hlsl.y | 89 ++++++++++--------- .../cast-componentwise-compatible.shader_test | 8 +- 2 files changed, 49 insertions(+), 48 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 3cc00f95..7ada218c 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -148,9 +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 convertible_data_type(struct hlsl_type *type) +static bool hlsl_types_are_componentwise_compatible(struct hlsl_ctx *ctx, struct hlsl_type *src, + struct hlsl_type *dst) { - return type->type != HLSL_CLASS_OBJECT; + unsigned int k, count = hlsl_type_component_count(dst); + + if (count > hlsl_type_component_count(src)) + return false; + + for (k = 0; k < count; ++k) + { + struct hlsl_type *src_comp_type, *dst_comp_type; + + src_comp_type = hlsl_type_get_component_type(ctx, src, k); + dst_comp_type = hlsl_type_get_component_type(ctx, dst, k); + + if ((src_comp_type->type != HLSL_CLASS_SCALAR || dst_comp_type->type != HLSL_CLASS_SCALAR) + && !hlsl_types_are_equal(src_comp_type, dst_comp_type)) + return false; + } + return true; }
static bool hlsl_types_are_componentwise_equal(struct hlsl_ctx *ctx, struct hlsl_type *src, @@ -174,58 +191,42 @@ static bool hlsl_types_are_componentwise_equal(struct hlsl_ctx *ctx, struct hlsl return true; }
-static bool compatible_data_types(struct hlsl_type *src, struct hlsl_type *dst) +static bool type_contains_only_numerics(struct hlsl_type *type) { - if (!convertible_data_type(src) || !convertible_data_type(dst)) - return false; + unsigned int i;
- if (src->type <= HLSL_CLASS_LAST_NUMERIC) + if (type->type == HLSL_CLASS_ARRAY) + return type_contains_only_numerics(type->e.array.type); + if (type->type == HLSL_CLASS_STRUCT) { - /* Scalar vars can be cast to pretty much everything */ - if (src->dimx == 1 && src->dimy == 1) - return true; - - if (src->type == HLSL_CLASS_VECTOR && dst->type == HLSL_CLASS_VECTOR) - return src->dimx >= dst->dimx; - } - - /* The other way around is true too i.e. whatever to scalar */ - if (dst->type <= HLSL_CLASS_LAST_NUMERIC && dst->dimx == 1 && dst->dimy == 1) + for (i = 0; i < type->e.record.field_count; ++i) + { + if (!type_contains_only_numerics(type->e.record.fields[i].type)) + return false; + } return true; - - if (src->type == HLSL_CLASS_ARRAY) - { - if (hlsl_types_are_equal(src->e.array.type, dst)) - /* e.g. float4[3] to float4 is allowed */ - return true; - - if (dst->type == HLSL_CLASS_ARRAY || dst->type == HLSL_CLASS_STRUCT) - return hlsl_type_component_count(src) >= hlsl_type_component_count(dst); - else - return hlsl_type_component_count(src) == hlsl_type_component_count(dst); } + return type->type <= HLSL_CLASS_LAST_NUMERIC; +}
- if (src->type == HLSL_CLASS_STRUCT) - return hlsl_type_component_count(src) >= hlsl_type_component_count(dst); +static bool compatible_data_types(struct hlsl_ctx *ctx, struct hlsl_type *src, struct hlsl_type *dst) +{ + if (src->type <= HLSL_CLASS_LAST_NUMERIC && src->dimx == 1 && src->dimy == 1 && type_contains_only_numerics(dst)) + return true;
- if (dst->type == HLSL_CLASS_ARRAY || dst->type == HLSL_CLASS_STRUCT) - return hlsl_type_component_count(src) == hlsl_type_component_count(dst); + if (src->type == HLSL_CLASS_MATRIX && dst->type == HLSL_CLASS_MATRIX + && src->dimx >= dst->dimx && src->dimy >= dst->dimy) + return true;
- if (src->type == HLSL_CLASS_MATRIX || dst->type == HLSL_CLASS_MATRIX) - { - if (src->type == HLSL_CLASS_MATRIX && dst->type == HLSL_CLASS_MATRIX && src->dimx >= dst->dimx && src->dimy >= dst->dimy) - return true; + if ((src->type == HLSL_CLASS_MATRIX && src->dimx > 1 && src->dimy > 1) + && hlsl_type_component_count(src) != hlsl_type_component_count(dst)) + return false;
- /* Matrix-vector conversion is apparently allowed if they have the same components count */ - if ((src->type == HLSL_CLASS_VECTOR || dst->type == HLSL_CLASS_VECTOR) - && hlsl_type_component_count(src) == hlsl_type_component_count(dst)) - return true; + if ((dst->type == HLSL_CLASS_MATRIX && dst->dimy > 1) + && hlsl_type_component_count(src) != hlsl_type_component_count(dst)) return false; - }
- if (hlsl_type_component_count(src) >= hlsl_type_component_count(dst)) - return true; - return false; + return hlsl_types_are_componentwise_compatible(ctx, src, dst); }
static bool implicit_compatible_data_types(struct hlsl_ctx *ctx, struct hlsl_type *src, struct hlsl_type *dst) @@ -4450,7 +4451,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 286c180b..4b342efb 100644 --- a/tests/cast-componentwise-compatible.shader_test +++ b/tests/cast-componentwise-compatible.shader_test @@ -159,8 +159,8 @@ float4 main() : sv_target
[test] -todo draw quad -todo probe all rgba (10.0, 20.0, 30.0, 30.0) +draw quad +probe all rgba (10.0, 20.0, 30.0, 30.0)
[pixel shader] @@ -181,5 +181,5 @@ float4 main() : sv_target
[test] -todo draw quad -todo probe all rgba (10.0, 10.0, 11.4, 12.4) +draw quad +probe all rgba (10.0, 10.0, 11.4, 12.4)
This merge request was approved by Zebediah Figura.
This merge request was approved by Giovanni Mascellani.
This merge request was approved by Henri Verbeet.