[PATCH vkd3d 5/8] vkd3d-shader/hlsl: Support initialization of implicit size arrays.
Giovanni Mascellani
gmascellani at codeweavers.com
Tue May 3 04:57:20 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.
---
libs/vkd3d-shader/hlsl.c | 13 ++-
libs/vkd3d-shader/hlsl.h | 3 +
libs/vkd3d-shader/hlsl.y | 94 +++++++++++++++++++
...lsl-initializer-implicit-array.shader_test | 12 +--
4 files changed, 114 insertions(+), 8 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c
index 95ce9445..ed94e903 100644
--- a/libs/vkd3d-shader/hlsl.c
+++ b/libs/vkd3d-shader/hlsl.c
@@ -165,6 +165,8 @@ static void hlsl_type_calculate_reg_size(struct hlsl_ctx *ctx, struct hlsl_type
{
unsigned int element_size = type->e.array.type->reg_size;
+ if (type->e.array.elements_count == HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT)
+ type->reg_size = 0;
if (is_sm4)
type->reg_size = (type->e.array.elements_count - 1) * align(element_size, 4) + element_size;
else
@@ -182,8 +184,10 @@ static void hlsl_type_calculate_reg_size(struct hlsl_ctx *ctx, struct hlsl_type
LIST_FOR_EACH_ENTRY(field, type->e.elements, struct hlsl_struct_field, entry)
{
unsigned int field_size = field->type->reg_size;
+ bool is_implicit_array = field->type->type == HLSL_CLASS_ARRAY &&
+ field->type->e.array.elements_count == HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT;
- assert(field_size);
+ assert(is_implicit_array || field_size);
type->reg_size = hlsl_type_get_sm4_offset(field->type, type->reg_size);
field->reg_offset = type->reg_size;
@@ -1022,7 +1026,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..1dce223a 100644
--- a/libs/vkd3d-shader/hlsl.h
+++ b/libs/vkd3d-shader/hlsl.h
@@ -139,6 +139,7 @@ struct hlsl_type
size_t bytecode_offset;
};
+
struct hlsl_semantic
{
const char *name;
@@ -227,6 +228,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..eb96a4c2 100644
--- a/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d-shader/hlsl.y
@@ -789,7 +789,26 @@ 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 cannot be implicit.");
+ }
+ else if (type->type == HLSL_CLASS_OBJECT)
+ {
+ hlsl_fixme(ctx, &v->loc, "Unbounded resource arrays.");
+ }
+ else
+ {
+ hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
+ "Implicit arrays not allowed in struct fieds.");
+ }
+ }
field->type = hlsl_new_array_type(ctx, field->type, v->arrays.sizes[i]);
+ }
vkd3d_free(v->arrays.sizes);
field->loc = v->loc;
field->name = v->name;
@@ -832,6 +851,11 @@ 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 arrays not allowed in typedefs.");
+ }
+
if (!(type = hlsl_new_array_type(ctx, type, v->arrays.sizes[i])))
{
free_parse_variable_def(v);
@@ -1604,8 +1628,57 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t
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 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 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)
+ {
+ hlsl_fixme(ctx, &v->loc, "Unbounded resource arrays.");
+ free_parse_initializer(&v->initializer);
+ v->initializer.args_count = 0;
+ }
+ else
+ {
+ hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Implicit 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 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]);
+ }
vkd3d_free(v->arrays.sizes);
if (type->type != HLSL_CLASS_MATRIX)
@@ -3186,6 +3259,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 +3814,13 @@ 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 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 b2a08d4b..5ddc0c89 100644
--- a/tests/hlsl-initializer-implicit-array.shader_test
+++ b/tests/hlsl-initializer-implicit-array.shader_test
@@ -6,8 +6,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 fail]
@@ -36,8 +36,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 fail]
@@ -182,8 +182,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 fail]
--
2.36.0
More information about the wine-devel
mailing list