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 | 45 +++++++++---------- tests/cast-broadcast.shader_test | 4 +- .../cast-componentwise-compatible.shader_test | 20 ++++----- 3 files changed, 33 insertions(+), 36 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index cc0a40ff..f5f114c8 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -284,30 +284,30 @@ 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) - { - assert(dst_type->dimx <= src_type->dimx); - assert(dst_type->dimy <= src_type->dimy); - } + 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); + assert(!matrix_cast || dst_type->dimx <= src_type->dimx); + assert(!matrix_cast || dst_type->dimy <= src_type->dimy);
if (!(var = hlsl_new_synthetic_var(ctx, "cast", dst_type, loc))) 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 +316,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]