[PATCH vkd3d v2 04/10] vkd3d-shader/hlsl: Support initialization of implicit size arrays.

Giovanni Mascellani gmascellani at codeweavers.com
Tue May 10 08:08:32 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'.
v6:
- Use 'true' instead of '1'.
- Reordered some error detection checks.
- Checking for shader model 5.1.
---
 libs/vkd3d-shader/hlsl.c                      |  14 ++-
 libs/vkd3d-shader/hlsl.h                      |   2 +
 libs/vkd3d-shader/hlsl.y                      | 119 ++++++++++++++++++
 ...lsl-initializer-implicit-array.shader_test |  16 +--
 4 files changed, 138 insertions(+), 13 deletions(-)

diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c
index 4bdd770a..c78b387c 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;
@@ -1026,7 +1025,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..698169d8 100644
--- a/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d-shader/hlsl.y
@@ -765,6 +765,11 @@ static void free_parse_variable_def(struct parse_variable_def *v)
     vkd3d_free(v);
 }
 
+static bool shader_is_sm_5_1(const struct hlsl_ctx *ctx)
+{
+    return ctx->profile->major_version == 5 && ctx->profile->minor_version >= 1;
+}
+
 static struct list *gen_struct_fields(struct hlsl_ctx *ctx,
         struct hlsl_type *type, unsigned int modifiers, struct list *fields)
 {
@@ -779,6 +784,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 +795,36 @@ 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 (type->type == HLSL_CLASS_OBJECT && shader_is_sm_5_1(ctx))
+                {
+                    if (i < v->arrays.count - 1)
+                    {
+                        hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
+                                "Inner array size cannot be implicit.");
+                    }
+                    else
+                    {
+                        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 +867,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 +1642,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 && shader_is_sm_5_1(ctx))
+                    {
+                        unbounded_res_array = true;
+                    }
+                    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 +3283,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 +3838,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