Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com --- v2: * Use "scalar_type" instead of "scal_type" * Use a vkd3d_string_buffer to format the variable's name * Format the variable name with %u instead of %x * Use hlsl_new_var_load() instead of hlsl_new_load() * Rename compute_matrix_offset() to add_compute_matrix_offset() --- libs/vkd3d-shader/hlsl.y | 89 +++++++++++++++++++++++++- tests/hlsl-matrix-indexing.shader_test | 8 +-- 2 files changed, 90 insertions(+), 7 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index ec0e23bb..d6d9dda6 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -581,6 +581,91 @@ static bool add_record_load(struct hlsl_ctx *ctx, struct list *instrs, struct hl return !!add_load(ctx, instrs, record, &c->node, field->type, loc); }
+static struct hlsl_ir_expr *add_binary_arithmetic_expr(struct hlsl_ctx *ctx, struct list *instrs, + enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2, + const struct vkd3d_shader_location *loc); + +static struct hlsl_ir_node *add_compute_matrix_offset(struct hlsl_ctx *ctx, struct list *instrs, + struct hlsl_type *type, struct hlsl_ir_node *x, struct hlsl_ir_node *y, + const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_node *major, *minor; + struct hlsl_ir_expr *mul, *add; + struct hlsl_ir_constant *four; + + if (type->modifiers & HLSL_MODIFIER_ROW_MAJOR) + { + minor = x; + major = y; + } + else + { + minor = y; + major = x; + } + + if (!(four = hlsl_new_uint_constant(ctx, 4, loc))) + return NULL; + list_add_tail(instrs, &four->node.entry); + + if (!(mul = add_binary_arithmetic_expr(ctx, instrs, HLSL_OP2_MUL, &four->node, major, loc))) + return NULL; + + if (!(add = add_binary_arithmetic_expr(ctx, instrs, HLSL_OP2_ADD, &mul->node, minor, loc))) + return NULL; + + return &add->node; +} + +static bool add_matrix_load(struct hlsl_ctx *ctx, struct list *instrs, + struct hlsl_ir_node *matrix, struct hlsl_ir_node *index, const struct vkd3d_shader_location *loc) +{ + struct hlsl_type *mat_type = matrix->data_type, *ret_type, *scalar_type; + struct vkd3d_string_buffer name; + static unsigned int counter = 0; + struct hlsl_ir_load *load; + struct hlsl_ir_var *var; + unsigned int i; + + ret_type = hlsl_get_vector_type(ctx, mat_type->base_type, mat_type->dimx); + scalar_type = hlsl_get_scalar_type(ctx, mat_type->base_type); + + vkd3d_string_buffer_init(&name); + vkd3d_string_buffer_printf(&name, "<index-%u>", counter++); + var = hlsl_new_synthetic_var(ctx, name.buffer, ret_type, *loc); + vkd3d_string_buffer_cleanup(&name); + if (!var) + return false; + + for (i = 0; i < mat_type->dimx; ++i) + { + struct hlsl_ir_node *offset; + struct hlsl_ir_store *store; + struct hlsl_ir_load *value; + struct hlsl_ir_constant *c; + + if (!(c = hlsl_new_uint_constant(ctx, i, loc))) + return false; + list_add_tail(instrs, &c->node.entry); + + if (!(offset = add_compute_matrix_offset(ctx, instrs, mat_type, &c->node, index, loc))) + return false; + + if (!(value = add_load(ctx, instrs, matrix, offset, scalar_type, *loc))) + return false; + + if (!(store = hlsl_new_store(ctx, var, &c->node, &value->node, 0, *loc))) + return false; + list_add_tail(instrs, &store->node.entry); + } + + if (!(load = hlsl_new_var_load(ctx, var, *loc))) + return false; + list_add_tail(instrs, &load->node.entry); + + return true; +} + static bool add_array_load(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *array, struct hlsl_ir_node *index, const struct vkd3d_shader_location loc) { @@ -597,9 +682,7 @@ static bool add_array_load(struct hlsl_ctx *ctx, struct list *instrs, struct hls } else if (expr_type->type == HLSL_CLASS_MATRIX) { - /* This needs to be lowered now, while we still have type information. */ - FIXME("Index of matrix type.\n"); - return false; + return add_matrix_load(ctx, instrs, array, index, &loc); } else if (expr_type->type == HLSL_CLASS_VECTOR) { diff --git a/tests/hlsl-matrix-indexing.shader_test b/tests/hlsl-matrix-indexing.shader_test index 8057179e..a0a89829 100644 --- a/tests/hlsl-matrix-indexing.shader_test +++ b/tests/hlsl-matrix-indexing.shader_test @@ -11,7 +11,7 @@ uniform 0 float4 1.0 2.0 3.0 4.0 uniform 4 float4 5.0 6.0 7.0 8.0 uniform 8 float4 9.0 10.0 11.0 12.0 uniform 12 float4 13.0 14.0 15.0 16.0 -todo draw quad +draw quad probe all rgba (1.0, 2.0, 10.0, 15.0)
[pixel shader] @@ -27,7 +27,7 @@ uniform 0 float4 1.0 2.0 3.0 4.0 uniform 4 float4 5.0 6.0 7.0 8.0 uniform 8 float4 9.0 10.0 11.0 12.0 uniform 12 float4 13.0 14.0 15.0 16.0 -todo draw quad +draw quad probe all rgba (1.0, 2.0, 10.0, 15.0)
[pixel shader] @@ -43,7 +43,7 @@ uniform 0 float4 1.0 2.0 3.0 4.0 uniform 4 float4 5.0 6.0 7.0 8.0 uniform 8 float4 9.0 10.0 11.0 12.0 uniform 12 float4 13.0 14.0 15.0 16.0 -todo draw quad +draw quad probe all rgba (1.0, 5.0, 7.0, 12.0)
[pixel shader] @@ -58,5 +58,5 @@ float4 main() : SV_TARGET [test] uniform 0 float4 1.0 2.0 3.0 0.0 uniform 4 float4 5.0 6.0 7.0 0.0 -todo draw quad +draw quad probe all rgba (1.0, 3.0, 6.0, 7.0)