Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/d3dcompiler_43/d3dcompiler_private.h | 2 +
dlls/d3dcompiler_43/hlsl.y | 61 ++++++++++++++++++++++-
dlls/d3dcompiler_43/tests/hlsl_d3d9.c | 59 ++++++++++++++++++++++
dlls/d3dcompiler_43/utils.c | 4 +-
4 files changed, 122 insertions(+), 4 deletions(-)
diff --git a/dlls/d3dcompiler_43/d3dcompiler_private.h b/dlls/d3dcompiler_43/d3dcompiler_private.h
index 2d8eba0b554..1a155736fd0 100644
--- a/dlls/d3dcompiler_43/d3dcompiler_private.h
+++ b/dlls/d3dcompiler_43/d3dcompiler_private.h
@@ -1154,8 +1154,10 @@ void add_function_decl(struct wine_rb_tree *funcs, char *name, struct hlsl_ir_fu
struct bwriter_shader *parse_hlsl_shader(const char *text, enum shader_type type, DWORD major, DWORD minor,
const char *entrypoint, char **messages) DECLSPEC_HIDDEN;
+const char *debug_base_type(const struct hlsl_type *type) DECLSPEC_HIDDEN;
const char *debug_hlsl_type(const struct hlsl_type *type) DECLSPEC_HIDDEN;
const char *debug_modifiers(DWORD modifiers) DECLSPEC_HIDDEN;
+const char *debug_node_type(enum hlsl_ir_node_type type) DECLSPEC_HIDDEN;
void debug_dump_ir_function_decl(const struct hlsl_ir_function_decl *func) DECLSPEC_HIDDEN;
void free_hlsl_type(struct hlsl_type *type) DECLSPEC_HIDDEN;
diff --git a/dlls/d3dcompiler_43/hlsl.y b/dlls/d3dcompiler_43/hlsl.y
index e46bdbade3f..46d815d0144 100644
--- a/dlls/d3dcompiler_43/hlsl.y
+++ b/dlls/d3dcompiler_43/hlsl.y
@@ -926,6 +926,47 @@ static struct list *make_list(struct hlsl_ir_node *node)
return list;
}
+static unsigned int evaluate_array_dimension(struct hlsl_ir_node *node)
+{
+ if (node->data_type->type != HLSL_CLASS_SCALAR)
+ return 0;
+
+ switch (node->type)
+ {
+ case HLSL_IR_CONSTANT:
+ {
+ struct hlsl_ir_constant *constant = constant_from_node(node);
+
+ switch (constant->node.data_type->base_type)
+ {
+ case HLSL_TYPE_UINT:
+ return constant->v.value.u[0];
+ case HLSL_TYPE_INT:
+ return constant->v.value.i[0];
+ case HLSL_TYPE_FLOAT:
+ return constant->v.value.f[0];
+ case HLSL_TYPE_DOUBLE:
+ return constant->v.value.d[0];
+ case HLSL_TYPE_BOOL:
+ return constant->v.value.b[0];
+ default:
+ WARN("Invalid type %s.\n", debug_base_type(constant->node.data_type));
+ return 0;
+ }
+ }
+ case HLSL_IR_CONSTRUCTOR:
+ case HLSL_IR_DEREF:
+ case HLSL_IR_EXPR:
+ case HLSL_IR_SWIZZLE:
+ FIXME("Unhandled type %s.\n", debug_node_type(node->type));
+ return 0;
+ case HLSL_IR_ASSIGNMENT:
+ default:
+ WARN("Invalid node type %s.\n", debug_node_type(node->type));
+ return 0;
+ }
+}
+
%}
%locations
@@ -1651,9 +1692,25 @@ array: /* Empty */
}
| '[' expr ']'
{
- FIXME("Array.\n");
- $$ = 0;
+ unsigned int size = evaluate_array_dimension(node_from_list($2));
+
free_instr_list($2);
+
+ if (!size)
+ {
+ hlsl_report_message(get_location(&@2), HLSL_LEVEL_ERROR,
+ "array size is not a positive integer constant\n");
+ YYABORT;
+ }
+ TRACE("Array size %u.\n", size);
+
+ if (size > 65536)
+ {
+ hlsl_report_message(get_location(&@2), HLSL_LEVEL_ERROR,
+ "array size must be between 1 and 65536");
+ YYABORT;
+ }
+ $$ = size;
}
var_modifiers: /* Empty */
diff --git a/dlls/d3dcompiler_43/tests/hlsl_d3d9.c b/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
index c673e2be327..525de9910be 100644
--- a/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
+++ b/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
@@ -654,10 +654,47 @@ static void test_return(void)
release_test_context(&test_context);
}
+static void test_array_dimensions(void)
+{
+ struct test_context test_context;
+ ID3D10Blob *ps_code = NULL;
+ struct vec4 v;
+
+ static const char shader[] =
+ "float4 main(float x : TEXCOORD0) : COLOR\n"
+ "{\n"
+ " const int dim = 4;\n"
+ " float a[2 * 2] = {0.1, 0.2, 0.3, 0.4};\n"
+ " float b[4.1] = a;\n"
+ " float c[dim] = b;\n"
+ " float d[true] = {c[0]};\n"
+ " float e[65536];\n"
+ " return float4(d[0], c[0], c[1], c[3]);\n"
+ "}";
+
+ if (!init_test_context(&test_context))
+ return;
+
+ todo_wine ps_code = compile_shader(shader, "ps_2_0");
+ if (ps_code)
+ {
+ draw_quad(test_context.device, ps_code);
+
+ v = get_color_vec4(test_context.device, 0, 0);
+ ok(compare_vec4(&v, 0.1f, 0.1f, 0.2f, 0.4f, 0),
+ "Got unexpected value {%.8e, %.8e, %.8e, %.8e}.\n", v.x, v.y, v.z, v.w);
+
+ ID3D10Blob_Release(ps_code);
+ }
+
+ release_test_context(&test_context);
+}
+
static void test_fail(void)
{
static const char *tests[] =
{
+ /* 0 */
"float4 test() : SV_TARGET\n"
"{\n"
" return y;\n"
@@ -689,6 +726,7 @@ static void test_fail(void)
" return float4(x.x, x.y, 0, 0);\n"
"}",
+ /* 5 */
"float4 test() : SV_TARGET\n"
"{\n"
" struct { int b,c; } x = {0};\n"
@@ -715,6 +753,26 @@ static void test_fail(void)
"{\n"
" return pos;\n"
"}",
+
+ /* 10 */
+ "float4 test(float2 pos: TEXCOORD0) : SV_TARGET\n"
+ "{\n"
+ " float a[0];\n"
+ " return float4(0, 0, 0, 0);\n"
+ "}",
+
+ "float4 test(float2 pos: TEXCOORD0) : SV_TARGET\n"
+ "{\n"
+ " float a[65537];\n"
+ " return float4(0, 0, 0, 0);\n"
+ "}",
+
+ "float4 test(float2 pos: TEXCOORD0) : SV_TARGET\n"
+ "{\n"
+ " int x;\n"
+ " float a[(x = 2)];\n"
+ " return float4(0, 0, 0, 0);\n"
+ "}",
};
static const char *targets[] = {"ps_2_0", "ps_3_0", "ps_4_0"};
@@ -776,5 +834,6 @@ START_TEST(hlsl_d3d9)
test_trig();
test_comma();
test_return();
+ test_array_dimensions();
test_fail();
}
diff --git a/dlls/d3dcompiler_43/utils.c b/dlls/d3dcompiler_43/utils.c
index 5eaff1730b3..fe2d23b623e 100644
--- a/dlls/d3dcompiler_43/utils.c
+++ b/dlls/d3dcompiler_43/utils.c
@@ -1652,7 +1652,7 @@ void init_functions_tree(struct wine_rb_tree *funcs)
wine_rb_init(&hlsl_ctx.functions, compare_function_rb);
}
-static const char *debug_base_type(const struct hlsl_type *type)
+const char *debug_base_type(const struct hlsl_type *type)
{
const char *name = "(unknown)";
@@ -1744,7 +1744,7 @@ const char *debug_modifiers(DWORD modifiers)
return wine_dbg_sprintf("%s", string[0] ? string + 1 : "");
}
-static const char *debug_node_type(enum hlsl_ir_node_type type)
+const char *debug_node_type(enum hlsl_ir_node_type type)
{
static const char * const names[] =
{
--
2.25.1