[PATCH vkd3d 2/8] vkd3d-shader/hlsl: Support initialization of implicit size arrays.
Giovanni Mascellani
gmascellani at codeweavers.com
Thu May 5 08:16:53 CDT 2022
From: Francisco Casas <fcasas at codeweavers.com>
HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT (zero) is used as a temporal value
for elements_count for implicit size arrays. It should be replaced by
the correct value after parsing the initializer.
In case the implicit array is not initialized correctly, hlsl_error()
is called but the array size is kept at 0. So the rest of the code
must handle these cases.
Signed-off-by: Francisco Casas <fcasas at codeweavers.com>
---
v2:
- Detection of incorrect use of implicit arrays was moved from the
parser rules to the respective add_* functions.
v3:
- Replaced 'if' with 'elif' in hlsl_type_calculate_reg_size().
- Updated changes to the new implicit array tests.
- Removed incorrect empty line.
- Fixed typo in error.
- Removed field_size assertion in hlsl_type_calculate_reg_size().
v4:
- Drop variables and struct fields declared as unbounded resource
arrays.
v5:
- Renamed 'implicit arrays' to 'implicit size arrays'.
---
libs/vkd3d-shader/hlsl.c | 14 ++-
libs/vkd3d-shader/hlsl.h | 2 +
libs/vkd3d-shader/hlsl.y | 111 ++++++++++++++++++
...lsl-initializer-implicit-array.shader_test | 16 +--
4 files changed, 130 insertions(+), 13 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c
index 7239b183..c74893ae 100644
--- a/libs/vkd3d-shader/hlsl.c
+++ b/libs/vkd3d-shader/hlsl.c
@@ -165,8 +165,9 @@ static void hlsl_type_calculate_reg_size(struct hlsl_ctx *ctx, struct hlsl_type
{
unsigned int element_size = type->e.array.type->reg_size;
- assert(element_size);
- if (is_sm4)
+ if (type->e.array.elements_count == HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT)
+ type->reg_size = 0;
+ else if (is_sm4)
type->reg_size = (type->e.array.elements_count - 1) * align(element_size, 4) + element_size;
else
type->reg_size = type->e.array.elements_count * element_size;
@@ -184,8 +185,6 @@ static void hlsl_type_calculate_reg_size(struct hlsl_ctx *ctx, struct hlsl_type
{
unsigned int field_size = field->type->reg_size;
- assert(field_size);
-
type->reg_size = hlsl_type_get_sm4_offset(field->type, type->reg_size);
field->reg_offset = type->reg_size;
type->reg_size += field_size;
@@ -1023,7 +1022,12 @@ struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const stru
}
for (t = type; t->type == HLSL_CLASS_ARRAY; t = t->e.array.type)
- vkd3d_string_buffer_printf(string, "[%u]", t->e.array.elements_count);
+ {
+ if (t->e.array.elements_count == HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT)
+ vkd3d_string_buffer_printf(string, "[]");
+ else
+ vkd3d_string_buffer_printf(string, "[%u]", t->e.array.elements_count);
+ }
return string;
}
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h
index 28b2ff1b..a142fa48 100644
--- a/libs/vkd3d-shader/hlsl.h
+++ b/libs/vkd3d-shader/hlsl.h
@@ -227,6 +227,8 @@ struct hlsl_src
#define HLSL_MODIFIERS_MAJORITY_MASK (HLSL_MODIFIER_ROW_MAJOR | HLSL_MODIFIER_COLUMN_MAJOR)
+#define HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT 0
+
struct hlsl_reg_reservation
{
char type;
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y
index 44e4964f..9fe454d0 100644
--- a/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d-shader/hlsl.y
@@ -779,6 +779,7 @@ static struct list *gen_struct_fields(struct hlsl_ctx *ctx,
return NULL;
LIST_FOR_EACH_ENTRY_SAFE(v, v_next, fields, struct parse_variable_def, entry)
{
+ bool unbounded_res_array = false;
unsigned int i;
if (!(field = hlsl_alloc(ctx, sizeof(*field))))
@@ -789,7 +790,33 @@ static struct list *gen_struct_fields(struct hlsl_ctx *ctx,
field->type = type;
for (i = 0; i < v->arrays.count; ++i)
+ {
+ if (v->arrays.sizes[i] == HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT)
+ {
+ if (i < v->arrays.count - 1)
+ {
+ hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
+ "Inner array size cannot be implicit.");
+ }
+ else if (type->type == HLSL_CLASS_OBJECT)
+ {
+ unbounded_res_array = true;
+ }
+ else
+ {
+ hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
+ "Implicit size arrays not allowed in struct fields.");
+ }
+ }
field->type = hlsl_new_array_type(ctx, field->type, v->arrays.sizes[i]);
+ }
+ if (unbounded_res_array)
+ {
+ hlsl_fixme(ctx, &v->loc, "Unbounded resource arrays as struct fields.");
+ free_parse_variable_def(v);
+ vkd3d_free(field);
+ continue;
+ }
vkd3d_free(v->arrays.sizes);
field->loc = v->loc;
field->name = v->name;
@@ -832,6 +859,12 @@ static bool add_typedef(struct hlsl_ctx *ctx, DWORD modifiers, struct hlsl_type
ret = true;
for (i = 0; i < v->arrays.count; ++i)
{
+ if (v->arrays.sizes[i] == HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT)
+ {
+ hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
+ "Implicit size arrays not allowed in typedefs.");
+ }
+
if (!(type = hlsl_new_array_type(ctx, type, v->arrays.sizes[i])))
{
free_parse_variable_def(v);
@@ -1601,11 +1634,67 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t
LIST_FOR_EACH_ENTRY_SAFE(v, v_next, var_list, struct parse_variable_def, entry)
{
+ bool unbounded_res_array = false;
unsigned int i;
type = basic_type;
+
for (i = 0; i < v->arrays.count; ++i)
+ {
+ if (v->arrays.sizes[i] == HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT)
+ {
+ unsigned int size = initializer_size(&v->initializer);
+ unsigned int elem_components = hlsl_type_component_count(type);
+
+ if (i < v->arrays.count - 1)
+ {
+ hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
+ "Inner array size cannot be implicit.");
+ free_parse_initializer(&v->initializer);
+ v->initializer.args_count = 0;
+ }
+ else if (elem_components == 0)
+ {
+ hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
+ "Cannot declare an implicit size array of a size 0 type.");
+ free_parse_initializer(&v->initializer);
+ v->initializer.args_count = 0;
+ }
+ else if (size == 0)
+ {
+ if (type->type == HLSL_CLASS_OBJECT)
+ {
+ unbounded_res_array = 1;
+ }
+ else
+ {
+ hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
+ "Implicit size arrays need to be initialized.");
+ free_parse_initializer(&v->initializer);
+ v->initializer.args_count = 0;
+ }
+ }
+ else if (size % elem_components != 0)
+ {
+ hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
+ "Cannot initialize implicit size array with %u components, expected a multiple of %u.",
+ size, elem_components);
+ free_parse_initializer(&v->initializer);
+ v->initializer.args_count = 0;
+ }
+ else
+ {
+ v->arrays.sizes[i] = size / elem_components;
+ }
+ }
type = hlsl_new_array_type(ctx, type, v->arrays.sizes[i]);
+ }
+ if (unbounded_res_array)
+ {
+ hlsl_fixme(ctx, &v->loc, "Unbounded resource arrays.");
+ free_parse_variable_def(v);
+ continue;
+ }
vkd3d_free(v->arrays.sizes);
if (type->type != HLSL_CLASS_MATRIX)
@@ -3186,6 +3275,21 @@ arrays:
$$.sizes = new_array;
$$.sizes[$$.count++] = size;
}
+ | '[' ']' arrays
+ {
+ uint32_t *new_array;
+
+ $$ = $3;
+
+ if (!(new_array = hlsl_realloc(ctx, $$.sizes, ($$.count + 1) * sizeof(*new_array))))
+ {
+ vkd3d_free($$.sizes);
+ YYABORT;
+ }
+
+ $$.sizes = new_array;
+ $$.sizes[$$.count++] = HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT;
+ }
var_modifiers:
%empty
@@ -3726,7 +3830,14 @@ unary_expr:
dst_type = $3;
for (i = 0; i < $4.count; ++i)
+ {
+ if ($4.sizes[i] == HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT)
+ {
+ hlsl_error(ctx, &@3, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
+ "Implicit size arrays not allowed in casts.");
+ }
dst_type = hlsl_new_array_type(ctx, dst_type, $4.sizes[i]);
+ }
if (!compatible_data_types(src_type, dst_type))
{
diff --git a/tests/hlsl-initializer-implicit-array.shader_test b/tests/hlsl-initializer-implicit-array.shader_test
index 648825eb..38c8234c 100644
--- a/tests/hlsl-initializer-implicit-array.shader_test
+++ b/tests/hlsl-initializer-implicit-array.shader_test
@@ -7,8 +7,8 @@ float4 main() : SV_TARGET
}
[test]
-todo draw quad
-todo probe all rgba (50, 60, 70, 80)
+draw quad
+probe all rgba (50, 60, 70, 80)
[pixel shader]
@@ -21,8 +21,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]
@@ -34,8 +34,8 @@ float4 main() : sv_target
}
[test]
-todo draw quad
-todo probe all rgba (7.0, 8.0, 9.0, 10.0)
+draw quad
+probe all rgba (7.0, 8.0, 9.0, 10.0)
[pixel shader]
@@ -62,8 +62,8 @@ float4 main() : SV_TARGET
}
[test]
-todo draw quad
-todo probe all rgba (318.0, 320.0, 322.0, 324.0)
+draw quad
+probe all rgba (318.0, 320.0, 322.0, 324.0)
[pixel shader fail]
--
2.36.0
More information about the wine-devel
mailing list