Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Henri Verbeet hverbeet@codeweavers.com --- libs/vkd3d-shader/hlsl_constant_ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_constant_ops.c b/libs/vkd3d-shader/hlsl_constant_ops.c index 2e16577f..d8787c21 100644 --- a/libs/vkd3d-shader/hlsl_constant_ops.c +++ b/libs/vkd3d-shader/hlsl_constant_ops.c @@ -278,10 +278,10 @@ static bool fold_div(struct hlsl_ctx *ctx, struct hlsl_ir_constant *dst, "Floating point division by zero."); } dst->value[k].f = src1->value[k].f / src2->value[k].f; - if (ctx->profile->major_version < 4 && isinf(dst->value[k].f)) + if (ctx->profile->major_version < 4 && !isfinite(dst->value[k].f)) { hlsl_error(ctx, &dst->node.loc, VKD3D_SHADER_ERROR_HLSL_DIVISION_BY_ZERO, - "Infinities are not allowed by the shader model."); + "Infinities and NaNs are not allowed by the shader model."); } break;
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Henri Verbeet hverbeet@codeweavers.com --- v4: * Restrict to shader model >= 4.0 --- tests/arithmetic-int.shader_test | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/tests/arithmetic-int.shader_test b/tests/arithmetic-int.shader_test index c2eee2ba..8b6d6d7c 100644 --- a/tests/arithmetic-int.shader_test +++ b/tests/arithmetic-int.shader_test @@ -41,3 +41,19 @@ float4 main() : SV_TARGET
return x % y; } + +[require] +shader model >= 4.0 + +[pixel shader] +float4 main() : SV_TARGET +{ + int x = -2147483648; + int y = -1; + + return x / y; +} + +[test] +draw quad +probe all rgba (-2147483648.0, -2147483648.0, -2147483648.0, -2147483648.0)
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Henri Verbeet hverbeet@codeweavers.com --- They would interfere with the following add_array_load() patch, because they would cause indices to be of type uint1 instead of uint. --- libs/vkd3d-shader/hlsl_codegen.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index f31bfe9f..5f1d5997 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -246,6 +246,7 @@ static bool lower_broadcasts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, v && src_type->type <= HLSL_CLASS_VECTOR && dst_type->type <= HLSL_CLASS_VECTOR && src_type->dimx == 1) { + struct hlsl_ir_node *replacement; struct hlsl_ir_swizzle *swizzle; struct hlsl_ir_expr *new_cast;
@@ -255,11 +256,17 @@ static bool lower_broadcasts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, v if (!(new_cast = hlsl_new_cast(ctx, cast->operands[0].node, dst_scalar_type, &cast->node.loc))) return false; list_add_after(&cast->node.entry, &new_cast->node.entry); - if (!(swizzle = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, X, X, X), dst_type->dimx, &new_cast->node, &cast->node.loc))) - return false; - list_add_after(&new_cast->node.entry, &swizzle->node.entry); + replacement = &new_cast->node;
- hlsl_replace_node(&cast->node, &swizzle->node); + if (dst_type->dimx != 1) + { + if (!(swizzle = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, X, X, X), dst_type->dimx, replacement, &cast->node.loc))) + return false; + list_add_after(&new_cast->node.entry, &swizzle->node.entry); + replacement = &swizzle->node; + } + + hlsl_replace_node(&cast->node, replacement); return true; }
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Henri Verbeet hverbeet@codeweavers.com --- v4: * Generate a multiplication only in the array branch. --- libs/vkd3d-shader/hlsl.y | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 291f8392..968f36ae 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -587,13 +587,18 @@ static bool add_array_load(struct hlsl_ctx *ctx, struct list *instrs, struct hls const struct hlsl_type *expr_type = array->data_type; struct hlsl_type *data_type; struct hlsl_ir_constant *c; - struct hlsl_ir_node *mul;
if (expr_type->type == HLSL_CLASS_ARRAY) { data_type = expr_type->e.array.type; + if (!(c = hlsl_new_uint_constant(ctx, hlsl_type_get_array_element_reg_size(data_type), &loc))) return false; + list_add_tail(instrs, &c->node.entry); + + if (!(index = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, index, &c->node))) + return false; + list_add_tail(instrs, &index->entry); } else if (expr_type->type == HLSL_CLASS_MATRIX) { @@ -604,8 +609,6 @@ static bool add_array_load(struct hlsl_ctx *ctx, struct list *instrs, struct hls else if (expr_type->type == HLSL_CLASS_VECTOR) { data_type = hlsl_get_scalar_type(ctx, expr_type->base_type); - if (!(c = hlsl_new_uint_constant(ctx, 1, &loc))) - return false; } else { @@ -616,12 +619,6 @@ static bool add_array_load(struct hlsl_ctx *ctx, struct list *instrs, struct hls return false; }
- list_add_tail(instrs, &c->node.entry); - if (!(mul = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, index, &c->node))) - return false; - list_add_tail(instrs, &mul->entry); - index = mul; - return !!add_load(ctx, instrs, array, index, data_type, loc); }
From: Francisco Casas fcasas@codeweavers.com
Signed-off-by: Francisco Casas fcasas@codeweavers.com Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Henri Verbeet hverbeet@codeweavers.com --- v3: * Patch reworked from scratch by Francisco * Some tests are still failing because they depend on matrix copying v4: * Renamed hlsl_compute_component_reg_offset() to hlsl_compute_component_offset(). * Removed 'loc' argument from hlsl_compute_component_offset(). * Removed comp_type != NULL checks. * Use '%' in HLSL_CLASS_ARRAY case. * Inlined initialize_var_from_initializer(). --- --- libs/vkd3d-shader/hlsl.c | 79 +++++++++++ libs/vkd3d-shader/hlsl.h | 2 + libs/vkd3d-shader/hlsl.y | 123 +++++------------- libs/vkd3d-shader/hlsl_codegen.c | 2 +- tests/hlsl-initializer-flatten.shader_test | 10 +- ...-initializer-invalid-arg-count.shader_test | 4 +- .../hlsl-initializer-local-array.shader_test | 4 +- tests/hlsl-initializer-nested.shader_test | 4 +- .../hlsl-initializer-static-array.shader_test | 4 +- tests/hlsl-initializer-struct.shader_test | 6 +- 10 files changed, 129 insertions(+), 109 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index eabe189f..7239b183 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -232,6 +232,85 @@ static struct hlsl_type *hlsl_new_type(struct hlsl_ctx *ctx, const char *name, e return type; }
+/* Returns the register offset of a given component within a type, given its index. + * *comp_type will be set to the type of the component. */ +unsigned int hlsl_compute_component_offset(struct hlsl_ctx *ctx, struct hlsl_type *type, + unsigned int idx, struct hlsl_type **comp_type) +{ + switch (type->type) + { + case HLSL_CLASS_SCALAR: + case HLSL_CLASS_VECTOR: + { + assert(idx < type->dimx * type->dimy); + *comp_type = hlsl_get_scalar_type(ctx, type->base_type); + return idx; + } + case HLSL_CLASS_MATRIX: + { + unsigned int minor, major, x = idx % type->dimx, y = idx / type->dimx; + + assert(idx < type->dimx * type->dimy); + + if (hlsl_type_is_row_major(type)) + { + minor = x; + major = y; + } + else + { + minor = y; + major = x; + } + + *comp_type = hlsl_get_scalar_type(ctx, type->base_type); + return 4 * major + minor; + } + + case HLSL_CLASS_ARRAY: + { + unsigned int elem_comp_count = hlsl_type_component_count(type->e.array.type); + unsigned int array_idx = idx / elem_comp_count; + unsigned int idx_in_elem = idx % elem_comp_count; + + assert(array_idx < type->e.array.elements_count); + + return array_idx * hlsl_type_get_array_element_reg_size(type->e.array.type) + + hlsl_compute_component_offset(ctx, type->e.array.type, idx_in_elem, comp_type); + } + + case HLSL_CLASS_STRUCT: + { + struct hlsl_struct_field *field; + + LIST_FOR_EACH_ENTRY(field, type->e.elements, struct hlsl_struct_field, entry) + { + unsigned int elem_comp_count = hlsl_type_component_count(field->type); + + if (idx < elem_comp_count) + { + return field->reg_offset + + hlsl_compute_component_offset(ctx, field->type, idx, comp_type); + } + idx -= elem_comp_count; + } + + assert(0); + return 0; + } + + case HLSL_CLASS_OBJECT: + { + assert(idx == 0); + *comp_type = type; + return 0; + } + } + + assert(0); + return 0; +} + struct hlsl_type *hlsl_new_array_type(struct hlsl_ctx *ctx, struct hlsl_type *basic_type, unsigned int array_size) { struct hlsl_type *type; diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 802adf87..28b2ff1b 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -786,6 +786,8 @@ struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, unsigned int default_majority, unsigned int modifiers); unsigned int hlsl_type_component_count(struct hlsl_type *type); unsigned int hlsl_type_get_array_element_reg_size(const struct hlsl_type *type); +unsigned int hlsl_compute_component_offset(struct hlsl_ctx *ctx, struct hlsl_type *type, + unsigned int idx, struct hlsl_type **comp_type); unsigned int hlsl_type_get_sm4_offset(const struct hlsl_type *type, unsigned int offset); bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2);
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 968f36ae..d67ffb79 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1450,77 +1450,44 @@ static bool add_increment(struct hlsl_ctx *ctx, struct list *instrs, bool decrem return true; }
-static void initialize_numeric_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, - struct parse_initializer *initializer, unsigned int reg_offset, struct hlsl_type *type, - unsigned int *initializer_offset) +static void initialize_var_components(struct hlsl_ctx *ctx, struct list *instrs, + struct hlsl_ir_var *dst, unsigned int *store_index, struct hlsl_ir_node *src, + const struct vkd3d_shader_location *loc) { - unsigned int i; - - if (type->type == HLSL_CLASS_MATRIX) - hlsl_fixme(ctx, &var->loc, "Matrix initializer."); + unsigned int src_comp_count = hlsl_type_component_count(src->data_type); + unsigned int k;
- for (i = 0; i < type->dimx; i++) + for (k = 0; k < src_comp_count; ++k) { + struct hlsl_type *dst_comp_type, *src_comp_type; + unsigned int dst_reg_offset, src_reg_offset; struct hlsl_ir_store *store; struct hlsl_ir_constant *c; - struct hlsl_ir_node *node; + struct hlsl_ir_load *load; + struct hlsl_ir_node *conv;
- node = initializer->args[*initializer_offset]; - *initializer_offset += 1; + dst_reg_offset = hlsl_compute_component_offset(ctx, dst->data_type, *store_index, &dst_comp_type); + src_reg_offset = hlsl_compute_component_offset(ctx, src->data_type, k, &src_comp_type);
- if (!(node = add_implicit_conversion(ctx, initializer->instrs, node, - hlsl_get_scalar_type(ctx, type->base_type), &node->loc))) + if (!(c = hlsl_new_uint_constant(ctx, src_reg_offset, loc))) return; + list_add_tail(instrs, &c->node.entry);
- if (!(c = hlsl_new_uint_constant(ctx, reg_offset + i, &node->loc))) + if (!(load = add_load(ctx, instrs, src, &c->node, src_comp_type, *loc))) return; - list_add_tail(initializer->instrs, &c->node.entry);
- if (!(store = hlsl_new_store(ctx, var, &c->node, node, 0, node->loc))) + if (!(conv = add_implicit_conversion(ctx, instrs, &load->node, dst_comp_type, loc))) return;
- list_add_tail(initializer->instrs, &store->node.entry); - } -} - -static void struct_var_initializer(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, - struct parse_initializer *initializer) -{ - struct hlsl_type *type = var->data_type; - struct hlsl_struct_field *field; - unsigned int i = 0; - - if (initializer_size(initializer) != hlsl_type_component_count(type)) - { - hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Expected %u components in initializer, but got %u.", - hlsl_type_component_count(type), initializer_size(initializer)); - return; - } - - LIST_FOR_EACH_ENTRY(field, type->e.elements, struct hlsl_struct_field, entry) - { - struct hlsl_ir_node *node = initializer->args[i]; - struct hlsl_ir_store *store; - struct hlsl_ir_constant *c; - - if (i++ >= initializer->args_count) - break; + if (!(c = hlsl_new_uint_constant(ctx, dst_reg_offset, loc))) + return; + list_add_tail(instrs, &c->node.entry);
- if (hlsl_type_component_count(field->type) == hlsl_type_component_count(node->data_type)) - { - if (!(c = hlsl_new_uint_constant(ctx, field->reg_offset, &node->loc))) - break; - list_add_tail(initializer->instrs, &c->node.entry); + if (!(store = hlsl_new_store(ctx, dst, &c->node, conv, 0, *loc))) + return; + list_add_tail(instrs, &store->node.entry);
- if (!(store = hlsl_new_store(ctx, var, &c->node, node, 0, node->loc))) - break; - list_add_tail(initializer->instrs, &store->node.entry); - } - else - { - hlsl_fixme(ctx, &node->loc, "Implicit cast in structure initializer."); - } + ++*store_index; } }
@@ -1648,51 +1615,23 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t if (v->initializer.braces) { unsigned int size = initializer_size(&v->initializer); - unsigned int initializer_offset = 0; + unsigned int store_index = 0; + unsigned int k;
- if (type->type <= HLSL_CLASS_LAST_NUMERIC && type->dimx * type->dimy != size) + if (hlsl_type_component_count(type) != size) { hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Expected %u components in numeric initializer, but got %u.", - type->dimx * type->dimy, v->initializer.args_count); + "Expected %u components in initializer, but got %u.", + hlsl_type_component_count(type), size); free_parse_initializer(&v->initializer); vkd3d_free(v); continue; }
- if ((type->type == HLSL_CLASS_STRUCT || type->type == HLSL_CLASS_ARRAY) - && hlsl_type_component_count(type) != size) - { - hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, - "Expected %u components in initializer, but got %u.", hlsl_type_component_count(type), size); - free_parse_initializer(&v->initializer); - vkd3d_free(v); - continue; - } - - if (type->type > HLSL_CLASS_LAST_NUMERIC && type->type != HLSL_CLASS_STRUCT) - { - FIXME("Initializers for non scalar/struct variables not supported yet.\n"); - free_parse_initializer(&v->initializer); - vkd3d_free(v); - continue; - } - - if (type->type == HLSL_CLASS_STRUCT) - { - struct_var_initializer(ctx, var, &v->initializer); - } - else + for (k = 0; k < v->initializer.args_count; ++k) { - if (v->initializer.args_count != size) - { - hlsl_fixme(ctx, &v->loc, "Flatten initializer."); - free_parse_initializer(&v->initializer); - vkd3d_free(v); - continue; - } - - initialize_numeric_var(ctx, var, &v->initializer, 0, type, &initializer_offset); + initialize_var_components(ctx, v->initializer.instrs, var, + &store_index, v->initializer.args[k], &v->initializer.args[k]->loc); } } else diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 5f1d5997..e945b94d 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1660,7 +1660,7 @@ bool hlsl_offset_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref if (*offset >= deref->var->data_type->reg_size) { hlsl_error(ctx, &deref->offset.node->loc, VKD3D_SHADER_ERROR_HLSL_OFFSET_OUT_OF_BOUNDS, - "Dereference is out of bounds."); + "Dereference is out of bounds. %u/%u", *offset, deref->var->data_type->reg_size); return false; }
diff --git a/tests/hlsl-initializer-flatten.shader_test b/tests/hlsl-initializer-flatten.shader_test index 3a430e0d..6b35c6b7 100644 --- a/tests/hlsl-initializer-flatten.shader_test +++ b/tests/hlsl-initializer-flatten.shader_test @@ -6,7 +6,7 @@ float4 main() : sv_target }
[test] -todo draw quad +draw quad probe all rgba (1, 2, 3, 4)
@@ -24,7 +24,7 @@ float4 main() : sv_target }
[test] -todo draw quad +draw quad probe all rgba (4, 5, 6, 7)
@@ -38,7 +38,7 @@ float4 main() : sv_target
[test] draw quad -todo probe all rgba (40, 10, 20, 30) +probe all rgba (40, 10, 20, 30)
[pixel shader] @@ -56,7 +56,7 @@ float4 main() : sv_target }
[test] -todo draw quad +draw quad probe all rgba (1.0, 2.0, 3.0, 4.0)
@@ -69,5 +69,5 @@ float4 main() : sv_target }
[test] -todo draw quad +draw quad probe all rgba (1.0, 2.0, 3.0, 4.0) diff --git a/tests/hlsl-initializer-invalid-arg-count.shader_test b/tests/hlsl-initializer-invalid-arg-count.shader_test index acd449af..4332fbe8 100644 --- a/tests/hlsl-initializer-invalid-arg-count.shader_test +++ b/tests/hlsl-initializer-invalid-arg-count.shader_test @@ -10,7 +10,7 @@ float4 main() : sv_target
[test] draw quad -todo probe all rgba (17, 18, 19, 20) +probe all rgba (17, 18, 19, 20)
[pixel shader fail] @@ -57,7 +57,7 @@ float4 main() : sv_target }
[test] -todo draw quad +draw quad probe all rgba (22, 23, 24, 25)
diff --git a/tests/hlsl-initializer-local-array.shader_test b/tests/hlsl-initializer-local-array.shader_test index 13670dc6..0862d4c9 100644 --- a/tests/hlsl-initializer-local-array.shader_test +++ b/tests/hlsl-initializer-local-array.shader_test @@ -11,7 +11,7 @@ float4 main() : SV_TARGET
[test] draw quad -todo probe all rgba (21, 22, 23, 24) +probe all rgba (21, 22, 23, 24)
[pixel shader] @@ -32,4 +32,4 @@ float4 main() : SV_TARGET
[test] draw quad -todo probe all rgba (71, 72, 73, 74) +probe all rgba (71, 72, 73, 74) diff --git a/tests/hlsl-initializer-nested.shader_test b/tests/hlsl-initializer-nested.shader_test index bcb37cf4..b00259c9 100644 --- a/tests/hlsl-initializer-nested.shader_test +++ b/tests/hlsl-initializer-nested.shader_test @@ -24,7 +24,7 @@ float4 main() : sv_target
[test] draw quad -todo probe all rgba (21, 22, 23, 24) +probe all rgba (21, 22, 23, 24)
[pixel shader] @@ -52,5 +52,5 @@ float4 main() : sv_target }
[test] -todo draw quad +draw quad probe all rgba (21, 22, 23, 24) diff --git a/tests/hlsl-initializer-static-array.shader_test b/tests/hlsl-initializer-static-array.shader_test index f276c629..57733502 100644 --- a/tests/hlsl-initializer-static-array.shader_test +++ b/tests/hlsl-initializer-static-array.shader_test @@ -12,7 +12,7 @@ float4 main() : SV_TARGET
[test] draw quad -todo probe all rgba (21, 22, 23, 24) +probe all rgba (21, 22, 23, 24)
[pixel shader] @@ -34,4 +34,4 @@ float4 main() : SV_TARGET
[test] draw quad -todo probe all rgba (61, 62, 63, 64) +probe all rgba (61, 62, 63, 64) diff --git a/tests/hlsl-initializer-struct.shader_test b/tests/hlsl-initializer-struct.shader_test index 2a824e23..f4028b5b 100644 --- a/tests/hlsl-initializer-struct.shader_test +++ b/tests/hlsl-initializer-struct.shader_test @@ -22,7 +22,7 @@ float4 main() : sv_target }
[test] -todo draw quad +draw quad probe all rgba (41, 42, 43, 44)
@@ -52,7 +52,7 @@ float4 main() : sv_target }
[test] -todo draw quad +draw quad probe all rgba (4311, 4312, 4313, 4314)
@@ -80,5 +80,5 @@ float4 main() : sv_target }
[test] -todo draw quad +draw quad probe all rgba (21, 22, 23, 24)
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Henri Verbeet hverbeet@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() v3: * Use the string buffer cache. * Rename add_matrix_load() to add_matrix_index() * Rename compute_matrix_offset() to add_matrix_scalar_load() and fold the add_load() call into it --- libs/vkd3d-shader/hlsl.y | 91 ++++++++++++++++++++++- tests/hlsl-initializer-matrix.shader_test | 8 +- tests/hlsl-matrix-indexing.shader_test | 8 +- 3 files changed, 96 insertions(+), 11 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index d67ffb79..9eb007a3 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -581,6 +581,93 @@ 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_matrix_scalar_load(struct hlsl_ctx *ctx, struct list *instrs, + struct hlsl_ir_node *matrix, 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; + struct hlsl_ir_load *load; + struct hlsl_type *type = matrix->data_type, *scalar_type; + + scalar_type = hlsl_get_scalar_type(ctx, type->base_type); + + 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; + + if (!(load = add_load(ctx, instrs, matrix, &add->node, scalar_type, *loc))) + return NULL; + + return &load->node; +} + +static bool add_matrix_index(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; + 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); + + name = vkd3d_string_buffer_get(&ctx->string_buffers); + vkd3d_string_buffer_printf(name, "<index-%u>", counter++); + var = hlsl_new_synthetic_var(ctx, name->buffer, ret_type, *loc); + vkd3d_string_buffer_release(&ctx->string_buffers, name); + if (!var) + return false; + + for (i = 0; i < mat_type->dimx; ++i) + { + struct hlsl_ir_store *store; + struct hlsl_ir_node *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 (!(value = add_matrix_scalar_load(ctx, instrs, matrix, &c->node, index, loc))) + return false; + + if (!(store = hlsl_new_store(ctx, var, &c->node, value, 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) { @@ -602,9 +689,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_index(ctx, instrs, array, index, &loc); } else if (expr_type->type == HLSL_CLASS_VECTOR) { diff --git a/tests/hlsl-initializer-matrix.shader_test b/tests/hlsl-initializer-matrix.shader_test index c4fafea7..790d402d 100644 --- a/tests/hlsl-initializer-matrix.shader_test +++ b/tests/hlsl-initializer-matrix.shader_test @@ -6,7 +6,7 @@ float4 main() : SV_TARGET }
[test] -todo draw quad +draw quad probe all rgba (21, 22, 23, 0)
@@ -18,7 +18,7 @@ float4 main() : SV_TARGET }
[test] -todo draw quad +draw quad probe all rgba (21, 22, 23, 0)
@@ -30,7 +30,7 @@ float4 main() : SV_TARGET }
[test] -todo draw quad +draw quad probe all rgba (21, 22, 23, 24)
@@ -42,7 +42,7 @@ float4 main() : SV_TARGET }
[test] -todo draw quad +draw quad probe all rgba (21, 22, 31, 32)
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)
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com --- v2: * Do not use the comma operator inside a "for" statement. * Prepend "add_" to the name of functions that mutate the instruction stream. * Add a vector and a matrix to the constructor test. v3: * Move the "idx++" expression in a dedicated statement. * Rewritten in the same philosphy as Francisco's initializers work v4: * Rewritten using initialize_var_components(). v5: * Fix compiler warnings. --- libs/vkd3d-shader/hlsl.y | 25 ++----------------- tests/hlsl-matrix-indexing.shader_test | 16 ++++++++++++ ...numeric-constructor-truncation.shader_test | 2 +- ...lsl-return-implicit-conversion.shader_test | 8 +++--- 4 files changed, 23 insertions(+), 28 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 9eb007a3..905dbfc5 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -2024,16 +2024,12 @@ static struct list *add_call(struct hlsl_ctx *ctx, const char *name, static struct list *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type *type, struct parse_initializer *params, struct vkd3d_shader_location loc) { - unsigned int i, writemask_offset = 0; - struct hlsl_ir_store *store; static unsigned int counter; struct hlsl_ir_load *load; struct hlsl_ir_var *var; + unsigned int i, idx = 0; char name[23];
- if (type->type == HLSL_CLASS_MATRIX) - hlsl_fixme(ctx, &loc, "Matrix constructor."); - sprintf(name, "<constructor-%x>", counter++); if (!(var = hlsl_new_synthetic_var(ctx, name, type, loc))) return NULL; @@ -2041,7 +2037,6 @@ static struct list *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type *type for (i = 0; i < params->args_count; ++i) { struct hlsl_ir_node *arg = params->args[i]; - unsigned int width;
if (arg->data_type->type == HLSL_CLASS_OBJECT) { @@ -2053,24 +2048,8 @@ static struct list *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type *type hlsl_release_string_buffer(ctx, string); continue; } - width = hlsl_type_component_count(arg->data_type); - - if (width > 4) - { - FIXME("Constructor argument with %u components.\n", width); - continue; - } - - if (!(arg = add_implicit_conversion(ctx, params->instrs, arg, - hlsl_get_vector_type(ctx, type->base_type, width), &arg->loc))) - continue; - - if (!(store = hlsl_new_store(ctx, var, NULL, arg, - ((1u << width) - 1) << writemask_offset, arg->loc))) - return NULL; - list_add_tail(params->instrs, &store->node.entry);
- writemask_offset += width; + initialize_var_components(ctx, params->instrs, var, &idx, arg, &loc); }
if (!(load = hlsl_new_var_load(ctx, var, loc))) diff --git a/tests/hlsl-matrix-indexing.shader_test b/tests/hlsl-matrix-indexing.shader_test index a0a89829..9336a67a 100644 --- a/tests/hlsl-matrix-indexing.shader_test +++ b/tests/hlsl-matrix-indexing.shader_test @@ -60,3 +60,19 @@ uniform 0 float4 1.0 2.0 3.0 0.0 uniform 4 float4 5.0 6.0 7.0 0.0 draw quad probe all rgba (1.0, 3.0, 6.0, 7.0) + +[pixel shader] +float4 main() : SV_TARGET +{ + float2x2 a = float2x2(11.0, 12.0, 13.0, 14.0); + float4x4 m = float4x4(1.0, 2.0, 3.0, 4.0, + float3(5.0, 6.0, 7.0), 8.0, + 9.0, 10.0, + a, + 15.0, 16.0); + return float4(m[0][0], m[1][0], m[1][2], m[2][3]); +} + +[test] +todo draw quad +probe all rgba (1.0, 5.0, 7.0, 12.0) diff --git a/tests/hlsl-numeric-constructor-truncation.shader_test b/tests/hlsl-numeric-constructor-truncation.shader_test index 27768dcc..f18b34d6 100644 --- a/tests/hlsl-numeric-constructor-truncation.shader_test +++ b/tests/hlsl-numeric-constructor-truncation.shader_test @@ -29,5 +29,5 @@ float4 main() : sv_target }
[test] -todo draw quad +draw quad probe all rgba (1.0, 2.0, 3.0, 5.0) diff --git a/tests/hlsl-return-implicit-conversion.shader_test b/tests/hlsl-return-implicit-conversion.shader_test index 38d21633..bf99d9cb 100644 --- a/tests/hlsl-return-implicit-conversion.shader_test +++ b/tests/hlsl-return-implicit-conversion.shader_test @@ -98,7 +98,7 @@ float4 main() : sv_target todo draw quad probe all rgba (0.4, 0.3, 0.2, 0.0)
-[pixel shader fail todo] +[pixel shader fail] float3x1 func() { return float1x3(0.4, 0.3, 0.2); @@ -109,7 +109,7 @@ float4 main() : sv_target return float4(func(), 0.0); }
-[pixel shader fail todo] +[pixel shader fail] float1x3 func() { return float3x1(0.4, 0.3, 0.2); @@ -191,7 +191,7 @@ float4 main() : sv_target todo draw quad probe all rgba (0.4, 0.3, 0.2, 0.0)
-[pixel shader fail todo] +[pixel shader fail] float3x1 func() { return float1x4(0.4, 0.3, 0.2, 0.1); @@ -217,7 +217,7 @@ float4 main() : sv_target todo draw quad probe all rgba (0.4, 0.3, 0.2, 0.0)
-[pixel shader fail todo] +[pixel shader fail] float1x3 func() { return float4x1(0.4, 0.3, 0.2, 0.1);
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com