[PATCH vkd3d 4/8] vkd3d-shader/hlsl: Support initialization of implicit size arrays.

Giovanni Mascellani gmascellani at codeweavers.com
Thu Apr 28 08:32:01 CDT 2022


From: Francisco Casas <fcasas at codeweavers.com>

HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT is used as a temporal value for
elements_count for implicit size arrays. It is replaced by the
correct value after parsing the initializer.

Signed-off-by: Francisco Casas <fcasas at codeweavers.com>
---
 libs/vkd3d-shader/hlsl.c                      | 13 ++++-
 libs/vkd3d-shader/hlsl.h                      |  2 +
 libs/vkd3d-shader/hlsl.y                      | 50 ++++++++++++++++++-
 libs/vkd3d-shader/hlsl_sm1.c                  |  1 +
 libs/vkd3d-shader/hlsl_sm4.c                  |  1 +
 ...lsl-initializer-implicit-array.shader_test |  4 +-
 6 files changed, 67 insertions(+), 4 deletions(-)

diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c
index 7239b183..1d272866 100644
--- a/libs/vkd3d-shader/hlsl.c
+++ b/libs/vkd3d-shader/hlsl.c
@@ -126,6 +126,7 @@ static bool hlsl_type_is_row_major(const struct hlsl_type *type)
 
 static unsigned int get_array_size(const struct hlsl_type *type)
 {
+    assert(type->e.array.elements_count != HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT);
     if (type->type == HLSL_CLASS_ARRAY)
         return get_array_size(type->e.array.type) * type->e.array.elements_count;
     return 1;
@@ -166,6 +167,7 @@ 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);
+            assert(type->e.array.elements_count != HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT);
             if (is_sm4)
                 type->reg_size = (type->e.array.elements_count - 1) * align(element_size, 4) + element_size;
             else
@@ -328,6 +330,9 @@ struct hlsl_type *hlsl_new_array_type(struct hlsl_ctx *ctx, struct hlsl_type *ba
 
     list_add_tail(&ctx->types, &type->entry);
 
+    if (type->e.array.elements_count == HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT)
+        TRACE("Implicit element count.\n");
+
     return type;
 }
 
@@ -410,6 +415,7 @@ unsigned int hlsl_type_component_count(struct hlsl_type *type)
     }
     if (type->type == HLSL_CLASS_ARRAY)
     {
+        assert(type->e.array.elements_count != HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT);
         return hlsl_type_component_count(type->e.array.type) * type->e.array.elements_count;
     }
     if (type->type != HLSL_CLASS_STRUCT)
@@ -1023,7 +1029,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, "[<undefined>]");
+                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..94597999 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 0xffffffff
+
 struct hlsl_reg_reservation
 {
     char type;
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y
index 905dbfc5..e7fe74d8 100644
--- a/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d-shader/hlsl.y
@@ -1606,7 +1606,27 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t
 
         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);
+
+                assert(v->initializer.args_count);
+
+                v->arrays.sizes[i] = (size + elem_components - 1)/elem_components;
+
+                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;
+                }
+            }
             type = hlsl_new_array_type(ctx, type, v->arrays.sizes[i]);
+        }
         vkd3d_free(v->arrays.sizes);
 
         if (type->type != HLSL_CLASS_MATRIX)
@@ -2464,6 +2484,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
 %token <name> TYPE_IDENTIFIER
 
 %type <arrays> arrays
+%type <arrays> implicit_arrays
 
 %type <assign_op> assign_op
 
@@ -3108,7 +3129,7 @@ variables_def:
         }
 
 variable_decl:
-      any_identifier arrays colon_attribute
+      any_identifier implicit_arrays colon_attribute
         {
             $$ = hlsl_alloc(ctx, sizeof(*$$));
             $$->loc = @1;
@@ -3137,6 +3158,15 @@ state_block:
 
 variable_def:
       variable_decl
+        {
+            if ($$->arrays.sizes && $$->arrays.sizes[$$->arrays.count - 1] == HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT)
+            {
+                hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_MISSING_INITIALIZER,
+                        "Implicit array requires initializer.");
+                free_parse_variable_def($$);
+                YYABORT;
+            }
+        }
     | variable_decl '=' complex_initializer
         {
             $$ = $1;
@@ -3188,6 +3218,24 @@ arrays:
             $$.sizes[$$.count++] = size;
         }
 
+implicit_arrays:
+      arrays
+    | '[' ']' 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
         {
diff --git a/libs/vkd3d-shader/hlsl_sm1.c b/libs/vkd3d-shader/hlsl_sm1.c
index 0cdd3917..30380fa2 100644
--- a/libs/vkd3d-shader/hlsl_sm1.c
+++ b/libs/vkd3d-shader/hlsl_sm1.c
@@ -234,6 +234,7 @@ static const struct hlsl_type *get_array_type(const struct hlsl_type *type)
 
 static unsigned int get_array_size(const struct hlsl_type *type)
 {
+    assert(type->e.array.elements_count != HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT);
     if (type->type == HLSL_CLASS_ARRAY)
         return get_array_size(type->e.array.type) * type->e.array.elements_count;
     return 1;
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c
index 8afa9333..2dcfdb88 100644
--- a/libs/vkd3d-shader/hlsl_sm4.c
+++ b/libs/vkd3d-shader/hlsl_sm4.c
@@ -252,6 +252,7 @@ static const struct hlsl_type *get_array_type(const struct hlsl_type *type)
 
 static unsigned int get_array_size(const struct hlsl_type *type)
 {
+    assert(type->e.array.elements_count != HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT);
     if (type->type == HLSL_CLASS_ARRAY)
         return get_array_size(type->e.array.type) * type->e.array.elements_count;
     return 1;
diff --git a/tests/hlsl-initializer-implicit-array.shader_test b/tests/hlsl-initializer-implicit-array.shader_test
index d2b94da4..91b6f049 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]
-- 
2.36.0




More information about the wine-devel mailing list