[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