From: Francisco Casas fcasas@codeweavers.com
--- Makefile.am | 1 + libs/vkd3d-shader/hlsl.y | 59 +++++++++++++++++++++++++ tests/hlsl-transpose.shader_test | 75 ++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 tests/hlsl-transpose.shader_test
diff --git a/Makefile.am b/Makefile.am index 85cd4642..d1f6ec6b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -117,6 +117,7 @@ vkd3d_shader_tests = \ tests/hlsl-struct-array.shader_test \ tests/hlsl-struct-assignment.shader_test \ tests/hlsl-struct-semantics.shader_test \ + tests/hlsl-transpose.shader_test \ tests/hlsl-vector-indexing.shader_test \ tests/hlsl-vector-indexing-uniform.shader_test \ tests/logic-operations.shader_test \ diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index eedc85bd..a18394a6 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -2596,6 +2596,64 @@ static bool intrinsic_saturate(struct hlsl_ctx *ctx, return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_SAT, arg, loc); }
+static bool intrinsic_transpose(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_node *arg = params->args[0]; + struct hlsl_type *arg_type = arg->data_type; + struct hlsl_deref var_deref; + struct hlsl_type *mat_type; + struct hlsl_ir_load *load; + struct hlsl_ir_var *var; + unsigned int i, j; + + if (arg_type->type != HLSL_CLASS_SCALAR && arg_type->type != HLSL_CLASS_MATRIX) + { + struct vkd3d_string_buffer *string; + + if ((string = hlsl_type_to_string(ctx, arg_type))) + hlsl_error(ctx, &arg->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Wrong type for argument 1 of transpose(): expected a matrix or scalar type, but got '%s'.\n", + string->buffer); + hlsl_release_string_buffer(ctx, string); + return false; + } + + if (arg_type->type == HLSL_CLASS_SCALAR) + { + list_add_tail(params->instrs, &arg->entry); + return true; + } + + mat_type = hlsl_get_matrix_type(ctx, arg_type->base_type, arg_type->dimy, arg_type->dimx); + + if (!(var = hlsl_new_synthetic_var(ctx, "transpose", mat_type, loc))) + return false; + hlsl_init_simple_deref_from_var(&var_deref, var); + + for (i = 0; i < arg_type->dimx; ++i) + { + for (j = 0; j < arg_type->dimy; ++j) + { + struct hlsl_ir_store *store; + struct hlsl_block block; + + if (!(load = add_load_component(ctx, params->instrs, arg, j * arg->data_type->dimx + i, loc))) + return false; + + if (!(store = hlsl_new_store_component(ctx, &block, &var_deref, i * var->data_type->dimx + j, &load->node))) + return false; + list_move_tail(params->instrs, &block.instrs); + } + } + + if (!(load = hlsl_new_var_load(ctx, var, *loc))) + return false; + list_add_tail(params->instrs, &load->node.entry); + + return true; +} + static const struct intrinsic_function { const char *name; @@ -2623,6 +2681,7 @@ intrinsic_functions[] = {"pow", 2, true, intrinsic_pow}, {"round", 1, true, intrinsic_round}, {"saturate", 1, true, intrinsic_saturate}, + {"transpose", 1, true, intrinsic_transpose}, };
static int intrinsic_function_name_compare(const void *a, const void *b) diff --git a/tests/hlsl-transpose.shader_test b/tests/hlsl-transpose.shader_test new file mode 100644 index 00000000..83852fa1 --- /dev/null +++ b/tests/hlsl-transpose.shader_test @@ -0,0 +1,75 @@ +[pixel shader] +float4 main() : sv_target +{ + return transpose(5); +} + +[test] +draw quad +probe all rgba (5.0, 5.0, 5.0, 5.0) + + +[pixel shader] +float4 main() : sv_target +{ + float1x1 x = 5; + + return transpose(x); +} + +[test] +draw quad +probe all rgba (5.0, 5.0, 5.0, 5.0) + + +[pixel shader fail] +float4 main() : sv_target +{ + float4 x = float4(1, 2, 3, 4); + + return transpose(x); +} + +[pixel shader] +float4 main() : sv_target +{ + float1x4 x = float1x4(1.0, 2.0, 3.0, 4.0); + + return transpose(x); +} + +[test] +draw quad +probe all rgba (1.0, 2.0, 3.0, 4.0) + + +[pixel shader] +float4 main() : sv_target +{ + float4x3 m = float4x3(1.0, 2.0, 3.0, + 4.0, 5.0, 6.0, + 7.0, 8.0, 9.0, + 10.0, 11.0, 12.0); + + return transpose(m)[1]; +} + +[test] +draw quad +probe all rgba (2.0, 5.0, 8.0, 11.0) + + +[pixel shader] +float4 main() : sv_target +{ + row_major float4x3 m = float4x3(1.0, 2.0, 3.0, + 4.0, 5.0, 6.0, + 7.0, 8.0, 9.0, + 10.0, 11.0, 12.0); + + return transpose(m)[1]; +} + +[test] +draw quad +probe all rgba (2.0, 5.0, 8.0, 11.0)