From: Zebediah Figura zfigura@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com Signed-off-by: Francisco Casas fcasas@codeweavers.com Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2: Get rid of the second comment entirely. I'm not sure that the C standard really allows a void return, but regardless it's probably not that important to bring that up here.
Makefile.am | 2 + tests/hlsl-function.shader_test | 164 ++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 tests/hlsl-function.shader_test
diff --git a/Makefile.am b/Makefile.am index 24257062..57cf5780 100644 --- a/Makefile.am +++ b/Makefile.am @@ -65,6 +65,7 @@ vkd3d_shader_tests = \ tests/hlsl-cross.shader_test \ tests/hlsl-duplicate-modifiers.shader_test \ tests/hlsl-for.shader_test \ + tests/hlsl-function.shader_test \ tests/hlsl-function-overload.shader_test \ tests/hlsl-gather-offset.shader_test \ tests/hlsl-gather.shader_test \ @@ -316,6 +317,7 @@ XFAIL_TESTS = \ tests/hlsl-bool-cast.shader_test \ tests/hlsl-duplicate-modifiers.shader_test \ tests/hlsl-for.shader_test \ + tests/hlsl-function.shader_test \ tests/hlsl-function-overload.shader_test \ tests/hlsl-gather.shader_test \ tests/hlsl-intrinsic-override.shader_test \ diff --git a/tests/hlsl-function.shader_test b/tests/hlsl-function.shader_test new file mode 100644 index 00000000..8d17605b --- /dev/null +++ b/tests/hlsl-function.shader_test @@ -0,0 +1,164 @@ +[pixel shader fail] + +float4 func(); + +float4 main() : sv_target +{ + return func(); +} + +% It's legal to call an undefined function in unused code, though. + +[pixel shader] + +float4 func(); + +float4 unused() +{ + return func(); +} + +float4 main() : sv_target +{ + return 0; +} + +[pixel shader fail] + +void func(inout float o) +{ + o += 0.1; +} + +float4 main() : sv_target +{ + float x = 0; + func(x + 1); + return 0; +} + +[pixel shader fail] + +void func(inout float2 o) +{ + o += 0.1; +} + +float4 main() : sv_target +{ + float2 x = 0; + func(x.yy); + return 0; +} + +[pixel shader fail] + +void func(out float o) +{ + o = 0.1; +} + +float4 main() : sv_target +{ + const float x = 0; + func(x); + return x; +} + +[pixel shader fail] + +void func(inout float o) +{ +} + +float4 main() : sv_target +{ + const float x = 0; + func(x); + return x; +} + +[pixel shader fail] + +void func() +{ +} + +float4 main() : sv_target +{ + return func(); +} + +[pixel shader fail] + +void foo() +{ +} + +void bar() +{ + return foo(); +} + +float4 main() : sv_target +{ + bar(); + return 0; +} + +[pixel shader fail] + +float4 main() : sv_target +{ + func(); + return 0; +} + +void func() +{ +} + +[pixel shader] + +float func(in float a, out float b, inout float c) +{ + c -= 0.2; + b = a * 2; + return a + 0.2; +} + +float4 main() : sv_target +{ + float x[2], ret; + + x[0] = 0.1; + x[1] = 0.9; + ret = func(0.3, x[0], x[1]); + + return float4(ret, x[0], x[1], 0); +} + +[test] +draw quad +probe all rgba (0.5, 0.6, 0.7, 0) + +[pixel shader] + +void func(in float a, inout float2 b) +{ + b.y += 0.1; + b *= a; +} + +float4 main() : sv_target +{ + float3 q = float3(0.1, 0.2, 0.3); + + func(3.0, q.zx); + func(0.5, q.yz); + return float4(q, 0); +} + +[test] +draw quad +probe all rgba (0.6, 0.1, 0.5, 0)
From: Zebediah Figura zfigura@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2: Get rid of the test failing on SM4 only.
Makefile.am | 2 + tests/hlsl-function-cast.shader_test | 87 ++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 tests/hlsl-function-cast.shader_test
diff --git a/Makefile.am b/Makefile.am index 57cf5780..e4f92bb5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -66,6 +66,7 @@ vkd3d_shader_tests = \ tests/hlsl-duplicate-modifiers.shader_test \ tests/hlsl-for.shader_test \ tests/hlsl-function.shader_test \ + tests/hlsl-function-cast.shader_test \ tests/hlsl-function-overload.shader_test \ tests/hlsl-gather-offset.shader_test \ tests/hlsl-gather.shader_test \ @@ -318,6 +319,7 @@ XFAIL_TESTS = \ tests/hlsl-duplicate-modifiers.shader_test \ tests/hlsl-for.shader_test \ tests/hlsl-function.shader_test \ + tests/hlsl-function-cast.shader_test \ tests/hlsl-function-overload.shader_test \ tests/hlsl-gather.shader_test \ tests/hlsl-intrinsic-override.shader_test \ diff --git a/tests/hlsl-function-cast.shader_test b/tests/hlsl-function-cast.shader_test new file mode 100644 index 00000000..4f80ac59 --- /dev/null +++ b/tests/hlsl-function-cast.shader_test @@ -0,0 +1,87 @@ +% Test implicit and explicit casts on function output parameters. + +[pixel shader] + +uniform float4 f; + +void func(out float4 o) +{ + o = f; +} + +float4 main() : sv_target +{ + int4 x; + func(x); + return x; +} + +[test] +uniform 0 float4 -1.9 -1.0 2.9 4.0 +draw quad +probe all rgba (-1.0, -1.0, 2.0, 4.0) + +% As above, but cast "x" to float4 first. + +[pixel shader] + +uniform float4 f; + +void func(out float4 o) +{ + o = f; +} + +float4 main() : sv_target +{ + int4 x; + func((float4)x); + return x; +} + +[test] +uniform 0 float4 -1.9 -1.0 2.9 4.0 +draw quad +probe all rgba (-1.0, -1.0, 2.0, 4.0) + +% As above, but declare "x" as float4 and cast it to int4. + +[pixel shader] + +uniform float4 f; + +void func(out float4 o) +{ + o = f; +} + +float4 main() : sv_target +{ + float4 x; + func((int4)x); + return x; +} + +[test] +uniform 0 float4 -1.9 -1.0 2.9 4.0 +draw quad +probe all rgba (-1.0, -1.0, 2.0, 4.0) + +[pixel shader] + +void func(inout float4 a) +{ + a += 0.1; +} + +float4 main(uniform int4 i) : sv_target +{ + int4 x = i; + func(x); + return x; +} + +[test] +uniform 0 int4 -2 0 1 -3000000 +draw quad +probe all rgba (-1.0, 0.0, 1.0, -3000000.0)
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
From: Zebediah Figura zfigura@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com Signed-off-by: Francisco Casas fcasas@codeweavers.com Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2: Tweak the error message.
libs/vkd3d-shader/hlsl.h | 2 +- libs/vkd3d-shader/hlsl_codegen.c | 25 ++++++++++++++++-------- libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 3 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index be515e32..043d7fb3 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -790,7 +790,7 @@ unsigned int hlsl_combine_writemasks(unsigned int first, unsigned int second); unsigned int hlsl_map_swizzle(unsigned int swizzle, unsigned int writemask); unsigned int hlsl_swizzle_from_writemask(unsigned int writemask);
-bool hlsl_offset_from_deref(const struct hlsl_deref *deref, unsigned int *offset); +bool hlsl_offset_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, unsigned int *offset); unsigned int hlsl_offset_from_deref_safe(struct hlsl_ctx *ctx, const struct hlsl_deref *deref); struct hlsl_reg hlsl_reg_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, const struct hlsl_type *type); diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 17a7649f..e416647f 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -349,15 +349,16 @@ static void copy_propagation_set_value(struct copy_propagation_var_def *var_def, } }
-static struct hlsl_ir_node *copy_propagation_compute_replacement(const struct copy_propagation_state *state, - const struct hlsl_deref *deref, unsigned int count, unsigned int *swizzle) +static struct hlsl_ir_node *copy_propagation_compute_replacement(struct hlsl_ctx *ctx, + const struct copy_propagation_state *state, const struct hlsl_deref *deref, + unsigned int count, unsigned int *swizzle) { const struct hlsl_ir_var *var = deref->var; struct copy_propagation_var_def *var_def; struct hlsl_ir_node *node = NULL; unsigned int offset, i;
- if (!hlsl_offset_from_deref(deref, &offset)) + if (!hlsl_offset_from_deref(ctx, deref, &offset)) return NULL;
if (!(var_def = copy_propagation_get_var_def(state, var))) @@ -414,7 +415,7 @@ static bool copy_propagation_transform_load(struct hlsl_ctx *ctx, return false; }
- if (!(new_node = copy_propagation_compute_replacement(state, &load->src, dimx, &swizzle))) + if (!(new_node = copy_propagation_compute_replacement(ctx, state, &load->src, dimx, &swizzle))) return false;
if (type->type != HLSL_CLASS_OBJECT) @@ -435,7 +436,7 @@ static bool copy_propagation_transform_object_load(struct hlsl_ctx *ctx, struct hlsl_ir_node *node; unsigned int swizzle;
- if (!(node = copy_propagation_compute_replacement(state, deref, 1, &swizzle))) + if (!(node = copy_propagation_compute_replacement(ctx, state, deref, 1, &swizzle))) return false;
/* Only HLSL_IR_LOAD can produce an object. */ @@ -468,7 +469,7 @@ static void copy_propagation_record_store(struct hlsl_ctx *ctx, struct hlsl_ir_s if (!(var_def = copy_propagation_create_var_def(ctx, state, var))) return;
- if (hlsl_offset_from_deref(lhs, &offset)) + if (hlsl_offset_from_deref(ctx, lhs, &offset)) { unsigned int writemask = store->writemask;
@@ -1546,7 +1547,7 @@ static bool type_is_single_reg(const struct hlsl_type *type) return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_VECTOR; }
-bool hlsl_offset_from_deref(const struct hlsl_deref *deref, unsigned int *offset) +bool hlsl_offset_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, unsigned int *offset) { struct hlsl_ir_node *offset_node = deref->offset.node;
@@ -1564,6 +1565,14 @@ bool hlsl_offset_from_deref(const struct hlsl_deref *deref, unsigned int *offset return false;
*offset = hlsl_ir_constant(offset_node)->value[0].u; + + 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."); + return false; + } + return true; }
@@ -1571,7 +1580,7 @@ unsigned int hlsl_offset_from_deref_safe(struct hlsl_ctx *ctx, const struct hlsl { unsigned int offset;
- if (hlsl_offset_from_deref(deref, &offset)) + if (hlsl_offset_from_deref(ctx, deref, &offset)) return offset;
hlsl_fixme(ctx, &deref->offset.node->loc, "Dereference with non-constant offset of type %s.", diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 1de67f45..5ab8494c 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -115,6 +115,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION = 5016, VKD3D_SHADER_ERROR_HLSL_NOT_IMPLEMENTED = 5017, VKD3D_SHADER_ERROR_HLSL_INVALID_TEXEL_OFFSET = 5018, + VKD3D_SHADER_ERROR_HLSL_OFFSET_OUT_OF_BOUNDS = 5019,
VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300,
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- Makefile.am | 1 - libs/vkd3d-shader/hlsl_codegen.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/Makefile.am b/Makefile.am index e4f92bb5..f3db6d06 100644 --- a/Makefile.am +++ b/Makefile.am @@ -315,7 +315,6 @@ XFAIL_TESTS = \ tests/hlsl-initializer-numeric.shader_test \ tests/hlsl-initializer-static-array.shader_test \ tests/hlsl-initializer-struct.shader_test \ - tests/hlsl-bool-cast.shader_test \ tests/hlsl-duplicate-modifiers.shader_test \ tests/hlsl-for.shader_test \ tests/hlsl-function.shader_test \ diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index e416647f..2aa13427 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1665,9 +1665,9 @@ int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun { progress = transform_ir(ctx, hlsl_fold_constants, body, NULL); progress |= copy_propagation_execute(ctx, body); + transform_ir(ctx, remove_trivial_swizzles, body, NULL); } while (progress); - transform_ir(ctx, remove_trivial_swizzles, body, NULL);
if (ctx->profile->major_version < 4) transform_ir(ctx, lower_division, body, NULL);
Hi,
Il 24/02/22 15:06, Matteo Bruni ha scritto:
--- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1665,9 +1665,9 @@ int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun { progress = transform_ir(ctx, hlsl_fold_constants, body, NULL); progress |= copy_propagation_execute(ctx, body);
transform_ir(ctx, remove_trivial_swizzles, body, NULL);
Wouldn't it make sense to "progress |=" this one too? I guess that removing a trivial swizzle can enable another round of constant folding or copy propagation.
Giovanni.
On Thu, Feb 24, 2022 at 4:05 PM Giovanni Mascellani gmascellani@codeweavers.com wrote:
Hi,
Il 24/02/22 15:06, Matteo Bruni ha scritto:
--- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1665,9 +1665,9 @@ int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun { progress = transform_ir(ctx, hlsl_fold_constants, body, NULL); progress |= copy_propagation_execute(ctx, body);
transform_ir(ctx, remove_trivial_swizzles, body, NULL);
Wouldn't it make sense to "progress |=" this one too? I guess that removing a trivial swizzle can enable another round of constant folding or copy propagation.
I remember thinking about it and dismissing it. Problem is, I don't know how I reached that conclusion.
I'll resend this patch with the change.
From: Zebediah Figura zfigura@codeweavers.com
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2: Improve comment in the shader test.
Makefile.am | 2 +- libs/vkd3d-shader/hlsl.c | 7 +++++++ libs/vkd3d-shader/hlsl.h | 1 + libs/vkd3d-shader/hlsl.y | 2 +- libs/vkd3d-shader/hlsl_codegen.c | 2 +- tests/hlsl-struct-array.shader_test | 19 +++++++++++++++++++ 6 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 tests/hlsl-struct-array.shader_test
diff --git a/Makefile.am b/Makefile.am index f3db6d06..85fadd38 100644 --- a/Makefile.am +++ b/Makefile.am @@ -93,6 +93,7 @@ vkd3d_shader_tests = \ tests/hlsl-state-block-syntax.shader_test \ tests/hlsl-static-initializer.shader_test \ tests/hlsl-storage-qualifiers.shader_test \ + tests/hlsl-struct-array.shader_test \ tests/hlsl-struct-assignment.shader_test \ tests/hlsl-struct-semantics.shader_test \ tests/hlsl-vector-indexing.shader_test \ @@ -325,7 +326,6 @@ XFAIL_TESTS = \ tests/hlsl-majority-pragma.shader_test \ tests/hlsl-majority-typedef.shader_test \ tests/hlsl-mul.shader_test \ - tests/hlsl-nested-arrays.shader_test \ tests/hlsl-numeric-constructor-truncation.shader_test \ tests/hlsl-numeric-types.shader_test \ tests/hlsl-operations.shader_test \ diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index a9a42770..a5aafdb9 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -202,6 +202,13 @@ static void hlsl_type_calculate_reg_size(struct hlsl_ctx *ctx, struct hlsl_type } }
+/* Returns the size of a type, considered as part of an array of that type. + * As such it includes padding after the type. */ +unsigned int hlsl_type_get_array_element_reg_size(const struct hlsl_type *type) +{ + return align(type->reg_size, 4); +} + static struct hlsl_type *hlsl_new_type(struct hlsl_ctx *ctx, const char *name, enum hlsl_type_class type_class, enum hlsl_base_type base_type, unsigned dimx, unsigned dimy) { diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 043d7fb3..8cce1273 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -782,6 +782,7 @@ bool hlsl_scope_add_type(struct hlsl_scope *scope, struct hlsl_type *type); 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_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 459ad03b..70109780 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -607,7 +607,7 @@ static struct hlsl_ir_load *add_array_load(struct hlsl_ctx *ctx, struct list *in return NULL; }
- if (!(c = hlsl_new_uint_constant(ctx, data_type->reg_size, loc))) + if (!(c = hlsl_new_uint_constant(ctx, hlsl_type_get_array_element_reg_size(data_type), loc))) return NULL; list_add_tail(instrs, &c->node.entry); if (!(mul = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, index, &c->node))) diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 2aa13427..6a8c512f 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -621,7 +621,7 @@ static bool split_array_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, if (type->type != HLSL_CLASS_ARRAY) return false; element_type = type->e.array.type; - element_size = element_type->reg_size; + element_size = hlsl_type_get_array_element_reg_size(element_type);
for (i = 0; i < type->e.array.elements_count; ++i) { diff --git a/tests/hlsl-struct-array.shader_test b/tests/hlsl-struct-array.shader_test new file mode 100644 index 00000000..a5df9cdb --- /dev/null +++ b/tests/hlsl-struct-array.shader_test @@ -0,0 +1,19 @@ +% In SM4, array elements are always aligned to the next vec4, although structs are not. + +[pixel shader] +uniform struct +{ + float p, q; +} colours[3]; + +float4 main() : sv_target +{ + return float4(colours[0].q, colours[1].p, colours[2].q, colours[2].p); +} + +[test] +uniform 0 float4 0.1 0.2 0.0 0.0 +uniform 4 float4 0.3 0.4 0.0 0.0 +uniform 8 float4 0.5 0.6 0.0 0.0 +draw quad +probe all rgba (0.2, 0.3, 0.6, 0.5)
Signed-off-by: Francisco Casas fcasas@codeweavers.com
However, the previous patch
vkd3d-shader/hlsl: Remove trivial swizzles after each copy prop pass.
is required first, otherwise hlsl-nested-arrays.shader_test and hlsl-struct-array.shader_test fail.
Which I guess is why Matteo wrote it.
Best regards, Francisco.
February 24, 2022 11:06 AM, "Matteo Bruni" mbruni@codeweavers.com wrote:
From: Zebediah Figura zfigura@codeweavers.com
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
v2: Improve comment in the shader test.
Makefile.am | 2 +- libs/vkd3d-shader/hlsl.c | 7 +++++++ libs/vkd3d-shader/hlsl.h | 1 + libs/vkd3d-shader/hlsl.y | 2 +- libs/vkd3d-shader/hlsl_codegen.c | 2 +- tests/hlsl-struct-array.shader_test | 19 +++++++++++++++++++ 6 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 tests/hlsl-struct-array.shader_test
diff --git a/Makefile.am b/Makefile.am index f3db6d06..85fadd38 100644 --- a/Makefile.am +++ b/Makefile.am @@ -93,6 +93,7 @@ vkd3d_shader_tests = \ tests/hlsl-state-block-syntax.shader_test \ tests/hlsl-static-initializer.shader_test \ tests/hlsl-storage-qualifiers.shader_test \
- tests/hlsl-struct-array.shader_test \
tests/hlsl-struct-assignment.shader_test \ tests/hlsl-struct-semantics.shader_test \ tests/hlsl-vector-indexing.shader_test \ @@ -325,7 +326,6 @@ XFAIL_TESTS = \ tests/hlsl-majority-pragma.shader_test \ tests/hlsl-majority-typedef.shader_test \ tests/hlsl-mul.shader_test \
- tests/hlsl-nested-arrays.shader_test \
tests/hlsl-numeric-constructor-truncation.shader_test \ tests/hlsl-numeric-types.shader_test \ tests/hlsl-operations.shader_test \ diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index a9a42770..a5aafdb9 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -202,6 +202,13 @@ static void hlsl_type_calculate_reg_size(struct hlsl_ctx *ctx, struct hlsl_type } }
+/* Returns the size of a type, considered as part of an array of that type.
- As such it includes padding after the type. */
+unsigned int hlsl_type_get_array_element_reg_size(const struct hlsl_type *type) +{
- return align(type->reg_size, 4);
+}
static struct hlsl_type *hlsl_new_type(struct hlsl_ctx *ctx, const char *name, enum hlsl_type_class type_class, enum hlsl_base_type base_type, unsigned dimx, unsigned dimy) { diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 043d7fb3..8cce1273 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -782,6 +782,7 @@ bool hlsl_scope_add_type(struct hlsl_scope *scope, struct hlsl_type *type); 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_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 459ad03b..70109780 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -607,7 +607,7 @@ static struct hlsl_ir_load *add_array_load(struct hlsl_ctx *ctx, struct list *in return NULL; }
- if (!(c = hlsl_new_uint_constant(ctx, data_type->reg_size, loc)))
- if (!(c = hlsl_new_uint_constant(ctx, hlsl_type_get_array_element_reg_size(data_type), loc)))
return NULL; list_add_tail(instrs, &c->node.entry); if (!(mul = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, index, &c->node))) diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 2aa13427..6a8c512f 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -621,7 +621,7 @@ static bool split_array_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, if (type->type != HLSL_CLASS_ARRAY) return false; element_type = type->e.array.type;
- element_size = element_type->reg_size;
- element_size = hlsl_type_get_array_element_reg_size(element_type);
for (i = 0; i < type->e.array.elements_count; ++i) { diff --git a/tests/hlsl-struct-array.shader_test b/tests/hlsl-struct-array.shader_test new file mode 100644 index 00000000..a5df9cdb --- /dev/null +++ b/tests/hlsl-struct-array.shader_test @@ -0,0 +1,19 @@ +% In SM4, array elements are always aligned to the next vec4, although structs are not.
+[pixel shader] +uniform struct +{
- float p, q;
+} colours[3];
+float4 main() : sv_target +{
- return float4(colours[0].q, colours[1].p, colours[2].q, colours[2].p);
+}
+[test] +uniform 0 float4 0.1 0.2 0.0 0.0 +uniform 4 float4 0.3 0.4 0.0 0.0 +uniform 8 float4 0.5 0.6 0.0 0.0 +draw quad
+probe all rgba (0.2, 0.3, 0.6, 0.5)
2.34.1