Wine-devel
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
January 2022
- 86 participants
- 717 discussions
[PATCH vkd3d 4/8] vkd3d-shader/hlsl: Prepare to swap switch order on fold_constants().
by Francisco Casas 17 Jan '22
by Francisco Casas 17 Jan '22
17 Jan '22
Signed-off-by: Francisco Casas <fcasas(a)codeweavers.com>
---
Don't mind about the 'goto fallback' too much, it is used transitionally
so that the tests still pass. It is removed in later patches.
Signed-off-by: Francisco Casas <fcasas(a)codeweavers.com>
---
libs/vkd3d-shader/hlsl_constant_ops.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_constant_ops.c b/libs/vkd3d-shader/hlsl_constant_ops.c
index 924e0380..3a778837 100644
--- a/libs/vkd3d-shader/hlsl_constant_ops.c
+++ b/libs/vkd3d-shader/hlsl_constant_ops.c
@@ -25,6 +25,7 @@ bool fold_constants(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *cont
struct hlsl_ir_constant *arg1, *arg2 = NULL, *res;
struct hlsl_ir_expr *expr;
unsigned int i, dimx;
+ bool success;
if (instr->type != HLSL_IR_EXPR)
return false;
@@ -44,6 +45,28 @@ bool fold_constants(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *cont
return false;
init_node(&res->node, HLSL_IR_CONSTANT, instr->data_type, instr->loc);
+ success = false;
+
+ switch (expr->op)
+ {
+ default:
+ goto fallback;
+ }
+
+ if (success)
+ {
+ list_add_before(&expr->node.entry, &res->node.entry);
+ hlsl_replace_node(&expr->node, &res->node);
+ return true;
+ }
+ else
+ {
+ vkd3d_free(res);
+ return false;
+ }
+
+fallback:
+
switch (instr->data_type->base_type)
{
case HLSL_TYPE_FLOAT:
--
2.25.1
3
2
[PATCH vkd3d 2/8] vkd3d-shader/hlsl: Rename replace_node() to hlsl_replace_node().
by Francisco Casas 17 Jan '22
by Francisco Casas 17 Jan '22
17 Jan '22
Signed-off-by: Francisco Casas <fcasas(a)codeweavers.com>
---
libs/vkd3d-shader/hlsl.c | 2 +-
libs/vkd3d-shader/hlsl.h | 2 +-
libs/vkd3d-shader/hlsl_codegen.c | 12 ++++++------
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c
index 3fb84b28..d92e731e 100644
--- a/libs/vkd3d-shader/hlsl.c
+++ b/libs/vkd3d-shader/hlsl.c
@@ -1384,7 +1384,7 @@ void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl
vkd3d_string_buffer_cleanup(&buffer);
}
-void replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new)
+void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new)
{
struct hlsl_src *src, *next;
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h
index 393b3f1f..530d12ad 100644
--- a/libs/vkd3d-shader/hlsl.h
+++ b/libs/vkd3d-shader/hlsl.h
@@ -680,7 +680,7 @@ void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl
int hlsl_emit_dxbc(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out);
-void replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new);
+void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new);
void hlsl_free_instr(struct hlsl_ir_node *node);
void hlsl_free_instr_list(struct list *list);
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c
index 00f3dae3..6cb4df8b 100644
--- a/libs/vkd3d-shader/hlsl_codegen.c
+++ b/libs/vkd3d-shader/hlsl_codegen.c
@@ -254,7 +254,7 @@ static bool lower_broadcasts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, v
return false;
list_add_after(&new_cast->node.entry, &swizzle->node.entry);
- replace_node(&cast->node, &swizzle->node);
+ hlsl_replace_node(&cast->node, &swizzle->node);
return true;
}
@@ -402,7 +402,7 @@ static bool copy_propagation_analyze_load(struct hlsl_ctx *ctx, struct hlsl_ir_l
if (!(swizzle_node = hlsl_new_swizzle(ctx, swizzle, type->dimx, new_node, &node->loc)))
return false;
list_add_before(&node->entry, &swizzle_node->node.entry);
- replace_node(node, &swizzle_node->node);
+ hlsl_replace_node(node, &swizzle_node->node);
return true;
}
@@ -490,7 +490,7 @@ static bool fold_redundant_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst
if (hlsl_types_are_equal(src_type, dst_type)
|| (src_type->base_type == dst_type->base_type && is_vec1(src_type) && is_vec1(dst_type)))
{
- replace_node(&expr->node, expr->operands[0].node);
+ hlsl_replace_node(&expr->node, expr->operands[0].node);
return true;
}
}
@@ -632,7 +632,7 @@ static bool lower_narrowing_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins
return false;
list_add_after(&new_cast->node.entry, &swizzle->node.entry);
- replace_node(&cast->node, &swizzle->node);
+ hlsl_replace_node(&cast->node, &swizzle->node);
return true;
}
@@ -741,7 +741,7 @@ static bool fold_constants(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, voi
}
list_add_before(&expr->node.entry, &res->node.entry);
- replace_node(&expr->node, &res->node);
+ hlsl_replace_node(&expr->node, &res->node);
return true;
}
@@ -761,7 +761,7 @@ static bool remove_trivial_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *i
if (((swizzle->swizzle >> (2 * i)) & 3) != i)
return false;
- replace_node(instr, swizzle->val.node);
+ hlsl_replace_node(instr, swizzle->val.node);
return true;
}
--
2.25.1
3
3
17 Jan '22
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
libs/vkd3d-shader/hlsl.y | 19 ++++++++++++++++++-
tests/round.shader_test | 13 +++++++++++++
tests/shader_runner_d3d12.c | 13 +++++++++++++
3 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y
index 636882c..6c285c3 100644
--- a/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d-shader/hlsl.y
@@ -1570,6 +1570,18 @@ static const struct hlsl_ir_function_decl *find_function_call(struct hlsl_ctx *c
return args.decl;
}
+static struct hlsl_ir_node *intrinsic_float_convert_arg(struct hlsl_ctx *ctx,
+ const struct parse_initializer *params, struct hlsl_ir_node *arg, const struct vkd3d_shader_location *loc)
+{
+ struct hlsl_type *type = arg->data_type;
+
+ if (type->base_type == HLSL_TYPE_FLOAT || type->base_type == HLSL_TYPE_HALF)
+ return arg;
+
+ type = hlsl_get_numeric_type(ctx, type->type, HLSL_TYPE_FLOAT, type->dimx, type->dimy);
+ return add_implicit_conversion(ctx, params->instrs, arg, type, loc);
+}
+
static bool intrinsic_abs(struct hlsl_ctx *ctx,
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
{
@@ -1675,7 +1687,12 @@ static bool intrinsic_pow(struct hlsl_ctx *ctx,
static bool intrinsic_round(struct hlsl_ctx *ctx,
const struct parse_initializer *params, const struct vkd3d_shader_location *loc)
{
- return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_ROUND, params->args[0], loc);
+ struct hlsl_ir_node *arg;
+
+ if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc)))
+ return false;
+
+ return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_ROUND, arg, loc);
}
static bool intrinsic_saturate(struct hlsl_ctx *ctx,
diff --git a/tests/round.shader_test b/tests/round.shader_test
index d8eb11b..cc5a697 100644
--- a/tests/round.shader_test
+++ b/tests/round.shader_test
@@ -24,3 +24,16 @@ float4 main(uniform float4 u) : sv_target
uniform 0 float4 -0.5 6.5 7.5 3.4
draw quad
probe all rgba (6.0, 8.0, 0.0, 3.0) 4
+
+
+
+[pixel shader]
+float4 main(uniform int4 u) : sv_target
+{
+ return round(u);
+}
+
+[test]
+uniform 0 int4 -1 0 2 10
+draw quad
+probe all rgba (-1.0, 0.0, 2.0, 10.0) 4
diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c
index 47f419b..c5992aa 100644
--- a/tests/shader_runner_d3d12.c
+++ b/tests/shader_runner_d3d12.c
@@ -552,6 +552,19 @@ static void parse_test_directive(struct shader_context *context, const char *lin
}
memcpy(context->uniforms + offset, &i, sizeof(i));
}
+ if (match_string(line, "int4", &line))
+ {
+ int v[4];
+
+ if (sscanf(line, "%d %d %d %d", &v[0], &v[1], &v[2], &v[3]) < 4)
+ fatal_error("Malformed int4 constant '%s'.\n", line);
+ if (offset + 4 > context->uniform_count)
+ {
+ context->uniform_count = offset + 4;
+ context->uniforms = realloc(context->uniforms, context->uniform_count * sizeof(*context->uniforms));
+ }
+ memcpy(context->uniforms + offset, v, sizeof(v));
+ }
else if (match_string(line, "uint", &line))
{
unsigned int u;
--
2.34.1
3
8
[PATCH vkd3d v2 1/7] tests: Separate the compile_shader function from the shader_test parser.
by Zebediah Figura 17 Jan '22
by Zebediah Figura 17 Jan '22
17 Jan '22
In essence, the goal is to separate the d3d12 backend. Just separate the compiler first, though, to make the diff easier to read.
NOTE TO SELF: Generate this diff with -C
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
Makefile.am | 41 +-
include/private/vkd3d_test.h | 19 +-
tests/shader_runner.c | 862 +++++++++++++++++++++++++++++++++++
tests/shader_runner.h | 29 ++
tests/shader_runner_d3d12.c | 847 +---------------------------------
5 files changed, 947 insertions(+), 851 deletions(-)
create mode 100644 tests/shader_runner.c
create mode 100644 tests/shader_runner.h
diff --git a/Makefile.am b/Makefile.am
index 20fee06d0..84aba0ee7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -50,9 +50,6 @@ vkd3d_cross_tests = \
tests/d3d12_invalid_usage \
tests/hlsl_d3d12
-vkd3d_shader_runners = \
- tests/shader_runner_d3d12
-
vkd3d_shader_tests = \
tests/abs.shader_test \
tests/cast-to-float.shader_test \
@@ -113,7 +110,8 @@ vkd3d_shader_tests = \
vkd3d_test_headers = \
tests/d3d12_crosstest.h \
- tests/d3d12_test_utils.h
+ tests/d3d12_test_utils.h \
+ tests/shader_runner.h
vkd3d_demos = \
demos/vkd3d-gears \
@@ -273,15 +271,18 @@ AM_DEFAULT_SOURCE_EXT = .c
TEST_EXTENSIONS = .shader_test
if BUILD_TESTS
-check_PROGRAMS = $(vkd3d_tests) $(vkd3d_cross_tests) $(vkd3d_shader_runners)
+check_PROGRAMS = $(vkd3d_tests) $(vkd3d_cross_tests) tests/shader_runner
TESTS = $(vkd3d_tests) $(vkd3d_cross_tests) $(vkd3d_shader_tests)
tests_d3d12_LDADD = $(LDADD) @PTHREAD_LIBS@ @VULKAN_LIBS@
tests_d3d12_invalid_usage_LDADD = $(LDADD) @VULKAN_LIBS@
tests_hlsl_d3d12_LDADD = $(LDADD) @VULKAN_LIBS@
-tests_shader_runner_d3d12_LDADD = $(LDADD) @VULKAN_LIBS@
+tests_shader_runner_LDADD = $(LDADD) @VULKAN_LIBS@
+tests_shader_runner_SOURCES = \
+ tests/shader_runner.c \
+ tests/shader_runner_d3d12.c
tests_vkd3d_api_LDADD = libvkd3d.la @VULKAN_LIBS@
tests_vkd3d_shader_api_LDADD = libvkd3d-shader.la
-SHADER_TEST_LOG_COMPILER = tests/shader_runner_d3d12
+SHADER_TEST_LOG_COMPILER = tests/shader_runner
XFAIL_TESTS = \
tests/cast-to-float.shader_test \
tests/cast-to-half.shader_test \
@@ -388,14 +389,17 @@ CROSS_CPPFLAGS = -I$(srcdir)/include -I$(srcdir)/include/private -I$(builddir)/i
CROSS_CFLAGS = -g -O2 -Wall -municode ${CROSS_CPPFLAGS}
EXTRA_DIST += $(cross_implibs:=.cross32.def) $(cross_implibs:=.cross64.def)
+shader_runner_cross_sources = \
+ $(srcdir)/tests/shader_runner.c \
+ $(srcdir)/tests/shader_runner_d3d12.c
+
if HAVE_CROSSTARGET32
CROSS32_CC = @CROSSCC32@
CROSS32_DLLTOOL = @CROSSTARGET32(a)-dlltool
CROSS32_IMPLIBS = $(cross_implibs:=.cross32.a)
CROSS32_EXEFILES = $(vkd3d_cross_tests:=.cross32.exe) \
- $(vkd3d_demos:demos/vkd3d-%=demos/%.cross32.exe) \
- $(vkd3d_shader_runners:=.cross32.exe)
-CROSS32_FILES = $(CROSS32_IMPLIBS) $(CROSS32_EXEFILES)
+ $(vkd3d_demos:demos/vkd3d-%=demos/%.cross32.exe)
+CROSS32_FILES = $(CROSS32_IMPLIBS) $(CROSS32_EXEFILES) tests/shader_runner.cross32.exe
CLEANFILES += $(CROSS32_FILES)
crosstest32: $(CROSS32_FILES)
@@ -411,6 +415,12 @@ $(CROSS32_EXEFILES): %.cross32.exe: %.c $(CROSS32_IMPLIBS) $(widl_headers)
$(AM_V_CCLD)depbase=`echo $@ | $(SED) 's![^/]*$$!$(DEPDIR)/&!;s!\.exe$$!!'`; \
$(CROSS32_CC) $(CROSS_CFLAGS) -MT $@ -MD -MP -MF $$depbase.Tpo -o $@ $< $(CROSS32_IMPLIBS) -ldxgi -lgdi32 -ld3dcompiler_47 && \
$(am__mv) $$depbase.Tpo $$depbase.Po
+
+tests/shader_runner.cross32.exe: $(shader_runner_cross_sources) $(CROSS32_IMPLIBS) $(widl_headers)
+ $(AM_V_CCLD)depbase=`echo $@ | sed 's![^/]*$$!$(DEPDIR)/&!;s!\.exe$$!!'`; \
+ $(CROSS32_CC) $(CROSS_CFLAGS) -MT $@ -MD -MP -MF $$depbase.Tpo -o $@ $(shader_runner_cross_sources) $(CROSS32_IMPLIBS) -ldxgi -lgdi32 -ld3dcompiler_47 && \
+ $(am__mv) $$depbase.Tpo $$depbase.Po
+
else
crosstest32:
endif
@@ -420,9 +430,8 @@ CROSS64_CC = @CROSSCC64@
CROSS64_DLLTOOL = @CROSSTARGET64(a)-dlltool
CROSS64_IMPLIBS = $(cross_implibs:=.cross64.a)
CROSS64_EXEFILES = $(vkd3d_cross_tests:=.cross64.exe) \
- $(vkd3d_demos:demos/vkd3d-%=demos/%.cross64.exe) \
- $(vkd3d_shader_runners:=.cross64.exe)
-CROSS64_FILES = $(CROSS64_IMPLIBS) $(CROSS64_EXEFILES)
+ $(vkd3d_demos:demos/vkd3d-%=demos/%.cross64.exe)
+CROSS64_FILES = $(CROSS64_IMPLIBS) $(CROSS64_EXEFILES) tests/shader_runner.cross64.exe
CLEANFILES += $(CROSS64_FILES)
crosstest64: $(CROSS64_FILES)
@@ -438,6 +447,12 @@ $(CROSS64_EXEFILES): %.cross64.exe: %.c $(CROSS64_IMPLIBS) $(widl_headers)
$(AM_V_CCLD)depbase=`echo $@ | sed 's![^/]*$$!$(DEPDIR)/&!;s!\.exe$$!!'`; \
$(CROSS64_CC) $(CROSS_CFLAGS) -MT $@ -MD -MP -MF $$depbase.Tpo -o $@ $< $(CROSS64_IMPLIBS) -ldxgi -lgdi32 -ld3dcompiler_47 && \
$(am__mv) $$depbase.Tpo $$depbase.Po
+
+tests/shader_runner.cross64.exe: $(shader_runner_cross_sources) $(CROSS64_IMPLIBS) $(widl_headers)
+ $(AM_V_CCLD)depbase=`echo $@ | sed 's![^/]*$$!$(DEPDIR)/&!;s!\.exe$$!!'`; \
+ $(CROSS64_CC) $(CROSS_CFLAGS) -MT $@ -MD -MP -MF $$depbase.Tpo -o $@ $(shader_runner_cross_sources) $(CROSS64_IMPLIBS) -ldxgi -lgdi32 -ld3dcompiler_47 && \
+ $(am__mv) $$depbase.Tpo $$depbase.Po
+
else
crosstest64:
endif
diff --git a/include/private/vkd3d_test.h b/include/private/vkd3d_test.h
index 6b8763dde..0cc7fe4f3 100644
--- a/include/private/vkd3d_test.h
+++ b/include/private/vkd3d_test.h
@@ -28,16 +28,15 @@
#include <stdlib.h>
#include <string.h>
-static void vkd3d_test_main(int argc, char **argv);
-static const char *vkd3d_test_name;
-static const char *vkd3d_test_platform = "other";
+extern const char *vkd3d_test_name;
+extern const char *vkd3d_test_platform;
static void vkd3d_test_start_todo(bool is_todo);
static int vkd3d_test_loop_todo(void);
static void vkd3d_test_end_todo(void);
#define START_TEST(name) \
- static const char *vkd3d_test_name = #name; \
+ const char *vkd3d_test_name = #name; \
static void vkd3d_test_main(int argc, char **argv)
/*
@@ -100,7 +99,7 @@ static void vkd3d_test_end_todo(void);
#define todo todo_if(true)
-static struct
+struct vkd3d_test_state
{
LONG success_count;
LONG failure_count;
@@ -120,7 +119,8 @@ static struct
const char *test_name_filter;
char context[1024];
-} vkd3d_test_state;
+};
+extern struct vkd3d_test_state vkd3d_test_state;
static bool
vkd3d_test_platform_is_windows(void)
@@ -253,6 +253,12 @@ vkd3d_test_debug(const char *fmt, ...)
printf("%s\n", buffer);
}
+#ifndef VKD3D_TEST_NO_DEFS
+const char *vkd3d_test_platform = "other";
+struct vkd3d_test_state vkd3d_test_state;
+
+static void vkd3d_test_main(int argc, char **argv);
+
int main(int argc, char **argv)
{
const char *test_filter = getenv("VKD3D_TEST_FILTER");
@@ -339,6 +345,7 @@ int wmain(int argc, WCHAR **wargv)
return ret;
}
#endif /* _WIN32 */
+#endif /* VKD3D_TEST_NO_DEFS */
typedef void (*vkd3d_test_pfn)(void);
diff --git a/tests/shader_runner.c b/tests/shader_runner.c
new file mode 100644
index 000000000..df4344881
--- /dev/null
+++ b/tests/shader_runner.c
@@ -0,0 +1,862 @@
+/*
+ * Copyright 2020-2021 Zebediah Figura for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/*
+ * This application contains code derived from piglit, the license for which
+ * follows:
+ *
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "d3d12_crosstest.h"
+#include "shader_runner.h"
+#include <errno.h>
+
+static void VKD3D_NORETURN VKD3D_PRINTF_FUNC(1, 2) fatal_error(const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ exit(1);
+}
+
+static bool vkd3d_array_reserve(void **elements, size_t *capacity, size_t element_count, size_t element_size)
+{
+ size_t new_capacity, max_capacity;
+ void *new_elements;
+
+ if (element_count <= *capacity)
+ return true;
+
+ max_capacity = ~(size_t)0 / element_size;
+ if (max_capacity < element_count)
+ return false;
+
+ new_capacity = max(*capacity, 4);
+ while (new_capacity < element_count && new_capacity <= max_capacity / 2)
+ new_capacity *= 2;
+
+ if (new_capacity < element_count)
+ new_capacity = element_count;
+
+ if (!(new_elements = realloc(*elements, new_capacity * element_size)))
+ return false;
+
+ *elements = new_elements;
+ *capacity = new_capacity;
+
+ return true;
+}
+
+enum texture_data_type
+{
+ TEXTURE_DATA_FLOAT,
+ TEXTURE_DATA_SINT,
+ TEXTURE_DATA_UINT,
+};
+
+struct sampler
+{
+ unsigned int slot;
+
+ D3D12_FILTER filter;
+ D3D12_TEXTURE_ADDRESS_MODE u_address, v_address, w_address;
+};
+
+struct texture
+{
+ unsigned int slot;
+
+ DXGI_FORMAT format;
+ enum texture_data_type data_type;
+ unsigned int texel_size;
+ unsigned int width, height;
+ uint8_t *data;
+ size_t data_size, data_capacity;
+
+ D3D12_DESCRIPTOR_RANGE descriptor_range;
+ ID3D12DescriptorHeap *heap;
+ ID3D12Resource *resource;
+ unsigned int root_index;
+};
+
+struct shader_context
+{
+ const struct shader_runner_ops *ops;
+
+ struct test_context c;
+
+ ID3D10Blob *ps_code;
+
+ uint32_t *uniforms;
+ size_t uniform_count;
+
+ struct texture *textures;
+ size_t texture_count;
+
+ struct sampler *samplers;
+ size_t sampler_count;
+};
+
+static void free_texture(struct texture *texture)
+{
+ ID3D12DescriptorHeap_Release(texture->heap);
+ ID3D12Resource_Release(texture->resource);
+ free(texture->data);
+ memset(texture, 0, sizeof(*texture));
+}
+
+enum parse_state
+{
+ STATE_NONE,
+ STATE_PREPROC,
+ STATE_PREPROC_INVALID,
+ STATE_SAMPLER,
+ STATE_SHADER_INVALID_PIXEL,
+ STATE_SHADER_PIXEL,
+ STATE_TEXTURE,
+ STATE_TEST,
+};
+
+static bool match_string(const char *line, const char *token, const char **const rest)
+{
+ size_t len = strlen(token);
+
+ if (strncmp(line, token, len) || !isspace(line[len]))
+ return false;
+ if (rest)
+ {
+ *rest = line + len;
+ while (isspace(**rest))
+ ++*rest;
+ }
+ return true;
+}
+
+static void parse_texture_format(struct texture *texture, const char *line)
+{
+ static const struct
+ {
+ const char *string;
+ enum texture_data_type data_type;
+ unsigned int texel_size;
+ DXGI_FORMAT format;
+ }
+ formats[] =
+ {
+ {"r32g32b32a32 float", TEXTURE_DATA_FLOAT, 16, DXGI_FORMAT_R32G32B32A32_FLOAT},
+ {"r32g32 uint", TEXTURE_DATA_UINT, 8, DXGI_FORMAT_R32G32_UINT},
+ {"r32 float", TEXTURE_DATA_FLOAT, 4, DXGI_FORMAT_R32_FLOAT},
+ {"r32 sint", TEXTURE_DATA_SINT, 4, DXGI_FORMAT_R32_SINT},
+ };
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(formats); ++i)
+ {
+ if (match_string(line, formats[i].string, &line))
+ {
+ texture->format = formats[i].format;
+ texture->data_type = formats[i].data_type;
+ texture->texel_size = formats[i].texel_size;
+ return;
+ }
+ }
+
+ fatal_error("Unknown format '%s'.\n", line);
+}
+
+static D3D12_TEXTURE_ADDRESS_MODE parse_sampler_address_mode(const char *line, const char **rest)
+{
+ if (match_string(line, "border", rest))
+ return D3D12_TEXTURE_ADDRESS_MODE_BORDER;
+ if (match_string(line, "clamp", rest))
+ return D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
+ if (match_string(line, "mirror_once", rest))
+ return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE;
+ if (match_string(line, "mirror", rest))
+ return D3D12_TEXTURE_ADDRESS_MODE_MIRROR;
+ if (match_string(line, "wrap", rest))
+ return D3D12_TEXTURE_ADDRESS_MODE_WRAP;
+
+ fatal_error("Unknown sampler address mode '%s'.\n", line);
+}
+
+static void parse_sampler_directive(struct sampler *sampler, const char *line)
+{
+ if (match_string(line, "address", &line))
+ {
+ sampler->u_address = parse_sampler_address_mode(line, &line);
+ sampler->v_address = parse_sampler_address_mode(line, &line);
+ sampler->w_address = parse_sampler_address_mode(line, &line);
+ }
+ else if (match_string(line, "filter", &line))
+ {
+ static const struct
+ {
+ const char *string;
+ D3D12_FILTER filter;
+ }
+ filters[] =
+ {
+ {"point point point", D3D12_FILTER_MIN_MAG_MIP_POINT},
+ {"point point linear", D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR},
+ {"point linear point", D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT},
+ {"point linear linear", D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR},
+ {"linear point point", D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT},
+ {"linear point linear", D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR},
+ {"linear linear point", D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT},
+ {"linear linear linear", D3D12_FILTER_MIN_MAG_MIP_LINEAR},
+ };
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(filters); ++i)
+ {
+ if (match_string(line, filters[i].string, &line))
+ {
+ sampler->filter = filters[i].filter;
+ return;
+ }
+ }
+
+ fatal_error("Unknown sampler filter '%s'.\n", line);
+ }
+ else
+ {
+ fatal_error("Unknown sampler directive '%s'.\n", line);
+ }
+}
+
+static void parse_texture_directive(struct texture *texture, const char *line)
+{
+ int ret;
+
+ if (match_string(line, "format", &line))
+ {
+ parse_texture_format(texture, line);
+ }
+ else if (match_string(line, "size", &line))
+ {
+ ret = sscanf(line, "( %u , %u )", &texture->width, &texture->height);
+ if (ret < 2)
+ fatal_error("Malformed texture size '%s'.\n", line);
+ }
+ else
+ {
+ union
+ {
+ float f;
+ int32_t i;
+ uint32_t u;
+ } u;
+ char *rest;
+
+ u.u = 0;
+
+ for (;;)
+ {
+ switch (texture->data_type)
+ {
+ case TEXTURE_DATA_FLOAT:
+ u.f = strtof(line, &rest);
+ break;
+
+ case TEXTURE_DATA_SINT:
+ u.i = strtol(line, &rest, 10);
+ break;
+
+ case TEXTURE_DATA_UINT:
+ u.u = strtoul(line, &rest, 10);
+ break;
+ }
+
+ if (rest == line)
+ break;
+
+ vkd3d_array_reserve((void **)&texture->data, &texture->data_capacity, texture->data_size + sizeof(u), 1);
+ memcpy(texture->data + texture->data_size, &u, sizeof(u));
+ texture->data_size += sizeof(u);
+ line = rest;
+ }
+ }
+}
+
+static void parse_test_directive(struct shader_context *context, const char *line)
+{
+ if (match_string(line, "draw quad", &line))
+ {
+ D3D12_SHADER_BYTECODE ps
+ = {ID3D10Blob_GetBufferPointer(context->ps_code), ID3D10Blob_GetBufferSize(context->ps_code)};
+ ID3D12GraphicsCommandList *command_list = context->c.list;
+ D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {0};
+ D3D12_ROOT_PARAMETER root_params[3], *root_param;
+ D3D12_STATIC_SAMPLER_DESC static_samplers[1];
+ static const float clear_color[4];
+ unsigned int uniform_index;
+ ID3D12PipelineState *pso;
+ HRESULT hr;
+ size_t i;
+
+ root_signature_desc.NumParameters = 0;
+ root_signature_desc.pParameters = root_params;
+ root_signature_desc.NumStaticSamplers = 0;
+ root_signature_desc.pStaticSamplers = static_samplers;
+
+ if (context->uniform_count)
+ {
+ uniform_index = root_signature_desc.NumParameters++;
+ root_param = &root_params[uniform_index];
+ root_param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
+ root_param->Constants.ShaderRegister = 0;
+ root_param->Constants.RegisterSpace = 0;
+ root_param->Constants.Num32BitValues = context->uniform_count;
+ root_param->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+ }
+
+ for (i = 0; i < context->texture_count; ++i)
+ {
+ struct texture *texture = &context->textures[i];
+ D3D12_DESCRIPTOR_RANGE *range = &texture->descriptor_range;
+ D3D12_SUBRESOURCE_DATA resource_data;
+
+ texture->root_index = root_signature_desc.NumParameters++;
+ root_param = &root_params[texture->root_index];
+ root_param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+ root_param->DescriptorTable.NumDescriptorRanges = 1;
+ root_param->DescriptorTable.pDescriptorRanges = range;
+ root_param->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+
+ range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+ range->NumDescriptors = 1;
+ range->BaseShaderRegister = texture->slot;
+ range->RegisterSpace = 0;
+ range->OffsetInDescriptorsFromTableStart = 0;
+
+ if (!texture->resource)
+ {
+ texture->heap = create_gpu_descriptor_heap(context->c.device,
+ D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1);
+ texture->resource = create_default_texture(context->c.device, texture->width, texture->height,
+ texture->format, 0, D3D12_RESOURCE_STATE_COPY_DEST);
+ resource_data.pData = texture->data;
+ resource_data.SlicePitch = resource_data.RowPitch = texture->width * texture->texel_size;
+ upload_texture_data(texture->resource, &resource_data, 1, context->c.queue, command_list);
+ reset_command_list(command_list, context->c.allocator);
+ transition_resource_state(command_list, texture->resource, D3D12_RESOURCE_STATE_COPY_DEST,
+ D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
+ ID3D12Device_CreateShaderResourceView(context->c.device, texture->resource,
+ NULL, get_cpu_descriptor_handle(&context->c, texture->heap, 0));
+ }
+ }
+
+ assert(root_signature_desc.NumParameters <= ARRAY_SIZE(root_params));
+
+ for (i = 0; i < context->sampler_count; ++i)
+ {
+ D3D12_STATIC_SAMPLER_DESC *sampler_desc = &static_samplers[root_signature_desc.NumStaticSamplers++];
+ const struct sampler *sampler = &context->samplers[i];
+
+ memset(sampler_desc, 0, sizeof(*sampler_desc));
+ sampler_desc->Filter = sampler->filter;
+ sampler_desc->AddressU = sampler->u_address;
+ sampler_desc->AddressV = sampler->v_address;
+ sampler_desc->AddressW = sampler->w_address;
+ sampler_desc->ShaderRegister = sampler->slot;
+ sampler_desc->RegisterSpace = 0;
+ sampler_desc->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+ }
+
+ if (context->c.root_signature)
+ ID3D12RootSignature_Release(context->c.root_signature);
+ hr = create_root_signature(context->c.device, &root_signature_desc, &context->c.root_signature);
+ ok(hr == S_OK, "Failed to create root signature, hr %#x.\n", hr);
+
+ pso = create_pipeline_state(context->c.device, context->c.root_signature, context->c.render_target_desc.Format,
+ NULL, &ps, NULL);
+ if (!pso)
+ return;
+ vkd3d_array_reserve((void **)&context->c.pso, &context->c.pso_capacity, context->c.pso_count + 1, sizeof(*context->c.pso));
+ context->c.pso[context->c.pso_count++] = pso;
+
+ ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context->c.root_signature);
+ if (context->uniform_count)
+ ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(command_list, uniform_index,
+ context->uniform_count, context->uniforms, 0);
+ for (i = 0; i < context->texture_count; ++i)
+ ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, context->textures[i].root_index,
+ get_gpu_descriptor_handle(&context->c, context->textures[i].heap, 0));
+
+ ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context->c.rtv, false, NULL);
+ ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context->c.scissor_rect);
+ ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context->c.viewport);
+ ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context->c.rtv, clear_color, 0, NULL);
+ ID3D12GraphicsCommandList_SetPipelineState(command_list, pso);
+ ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0);
+ transition_resource_state(command_list, context->c.render_target,
+ D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
+ }
+ else if (match_string(line, "probe all rgba", &line))
+ {
+ unsigned int ulps;
+ struct vec4 v;
+ int ret;
+
+ ret = sscanf(line, "( %f , %f , %f , %f ) %u", &v.x, &v.y, &v.z, &v.w, &ulps);
+ if (ret < 4)
+ fatal_error("Malformed probe arguments '%s'.\n", line);
+ if (ret < 5)
+ ulps = 0;
+ check_sub_resource_vec4(context->c.render_target, 0, context->c.queue, context->c.list, &v, ulps);
+ reset_command_list(context->c.list, context->c.allocator);
+ }
+ else if (match_string(line, "probe rect rgba", &line))
+ {
+ unsigned int x, y, w, h, ulps;
+ struct resource_readback rb;
+ struct vec4 v;
+ RECT rect;
+ int ret;
+
+ ret = sscanf(line, "( %u , %u , %u , %u ) ( %f , %f , %f , %f ) %u",
+ &x, &y, &w, &h, &v.x, &v.y, &v.z, &v.w, &ulps);
+ if (ret < 8)
+ fatal_error("Malformed probe arguments '%s'.\n", line);
+ if (ret < 9)
+ ulps = 0;
+
+ get_texture_readback_with_command_list(context->c.render_target, 0, &rb, context->c.queue, context->c.list);
+ rect.left = x;
+ rect.right = x + w;
+ rect.top = y;
+ rect.bottom = y + h;
+ check_readback_data_vec4(&rb, &rect, &v, ulps);
+ release_resource_readback(&rb);
+ reset_command_list(context->c.list, context->c.allocator);
+ }
+ else if (match_string(line, "probe rgba", &line))
+ {
+ struct resource_readback rb;
+ unsigned int x, y, ulps;
+ struct vec4 v;
+ RECT rect;
+ int ret;
+
+ ret = sscanf(line, "( %u , %u ) ( %f , %f , %f , %f ) %u", &x, &y, &v.x, &v.y, &v.z, &v.w, &ulps);
+ if (ret < 6)
+ fatal_error("Malformed probe arguments '%s'.\n", line);
+ if (ret < 7)
+ ulps = 0;
+
+ get_texture_readback_with_command_list(context->c.render_target, 0, &rb, context->c.queue, context->c.list);
+ rect.left = x;
+ rect.right = x + 1;
+ rect.top = y;
+ rect.bottom = y + 1;
+ check_readback_data_vec4(&rb, &rect, &v, ulps);
+ release_resource_readback(&rb);
+ reset_command_list(context->c.list, context->c.allocator);
+ }
+ else if (match_string(line, "uniform", &line))
+ {
+ unsigned int offset;
+
+ if (!sscanf(line, "%u", &offset))
+ fatal_error("Unknown uniform type '%s'.\n", line);
+ line = strchr(line, ' ') + 1;
+
+ if (match_string(line, "float4", &line))
+ {
+ struct vec4 v;
+
+ if (sscanf(line, "%f %f %f %f", &v.x, &v.y, &v.z, &v.w) < 4)
+ fatal_error("Malformed float4 constant '%s'.\n", line);
+ if (offset + 4 > context->uniform_count)
+ {
+ context->uniform_count = offset + 4;
+ context->uniforms = realloc(context->uniforms, context->uniform_count * sizeof(*context->uniforms));
+ }
+ memcpy(context->uniforms + offset, &v, sizeof(v));
+ }
+ else if (match_string(line, "float", &line))
+ {
+ float f;
+
+ if (sscanf(line, "%f", &f) < 1)
+ fatal_error("Malformed float constant '%s'.\n", line);
+ if (offset + 1 > context->uniform_count)
+ {
+ context->uniform_count = offset + 1;
+ context->uniforms = realloc(context->uniforms, context->uniform_count * sizeof(*context->uniforms));
+ }
+ memcpy(context->uniforms + offset, &f, sizeof(f));
+ }
+ else if (match_string(line, "int", &line))
+ {
+ int i;
+
+ if (sscanf(line, "%i", &i) < 1)
+ fatal_error("Malformed int constant '%s'.\n", line);
+ if (offset + 1 > context->uniform_count)
+ {
+ context->uniform_count = offset + 1;
+ context->uniforms = realloc(context->uniforms, context->uniform_count * sizeof(*context->uniforms));
+ }
+ memcpy(context->uniforms + offset, &i, sizeof(i));
+ }
+ else if (match_string(line, "uint", &line))
+ {
+ unsigned int u;
+
+ if (sscanf(line, "%u", &u) < 1)
+ fatal_error("Malformed uint constant '%s'.\n", line);
+ if (offset + 1 > context->uniform_count)
+ {
+ context->uniform_count = offset + 1;
+ context->uniforms = realloc(context->uniforms, context->uniform_count * sizeof(*context->uniforms));
+ }
+ memcpy(context->uniforms + offset, &u, sizeof(u));
+ }
+ }
+ else
+ {
+ fatal_error("Unknown test directive '%s'.\n", line);
+ }
+}
+
+static struct sampler *get_sampler(struct shader_context *context, unsigned int slot)
+{
+ struct sampler *sampler;
+ size_t i;
+
+ for (i = 0; i < context->sampler_count; ++i)
+ {
+ sampler = &context->samplers[i];
+
+ if (sampler->slot == slot)
+ return sampler;
+ }
+
+ return NULL;
+}
+
+static struct texture *get_texture(struct shader_context *context, unsigned int slot)
+{
+ struct texture *texture;
+ size_t i;
+
+ for (i = 0; i < context->texture_count; ++i)
+ {
+ texture = &context->textures[i];
+ if (texture->slot == slot)
+ return texture;
+ }
+
+ return NULL;
+}
+
+void run_shader_tests(int argc, char **argv, const struct shader_runner_ops *ops)
+{
+ static const struct test_context_desc desc =
+ {
+ .rt_width = 640,
+ .rt_height = 480,
+ .no_root_signature = true,
+ .rt_format = DXGI_FORMAT_R32G32B32A32_FLOAT,
+ };
+ size_t shader_source_size = 0, shader_source_len = 0;
+ struct sampler *current_sampler = NULL;
+ struct texture *current_texture = NULL;
+ enum parse_state state = STATE_NONE;
+ unsigned int i, line_number = 0;
+ struct shader_context context;
+ const char *filename = NULL;
+ char *shader_source = NULL;
+ char line[256];
+ FILE *f;
+
+ parse_args(argc, argv);
+ enable_d3d12_debug_layer(argc, argv);
+ init_adapter_info();
+
+ for (i = 1; i < argc; ++i)
+ {
+ if (argv[i][0] != '-')
+ {
+ filename = argv[i];
+ break;
+ }
+ }
+
+ if (!filename)
+ {
+ fprintf(stderr, "Usage: %s [file]\n", argv[0]);
+ return;
+ }
+
+ if (!(f = fopen(filename, "r")))
+ {
+ fatal_error("Unable to open '%s' for reading: %s\n", argv[1], strerror(errno));
+ return;
+ }
+
+ memset(&context, 0, sizeof(context));
+ context.ops = ops;
+ init_test_context(&context.c, &desc);
+
+ for (;;)
+ {
+ char *ret = fgets(line, sizeof(line), f);
+
+ ++line_number;
+
+ if (!ret || line[0] == '[')
+ {
+ switch (state)
+ {
+ case STATE_NONE:
+ case STATE_SAMPLER:
+ case STATE_TEST:
+ case STATE_TEXTURE:
+ break;
+
+ case STATE_SHADER_PIXEL:
+ if (!(context.ps_code = context.ops->compile_shader(shader_source)))
+ return;
+ shader_source_len = 0;
+ break;
+
+ case STATE_SHADER_INVALID_PIXEL:
+ {
+ ID3D10Blob *blob = NULL, *errors = NULL;
+ HRESULT hr;
+
+ hr = D3DCompile(shader_source, strlen(shader_source), NULL,
+ NULL, NULL, "main", "ps_4_0", 0, 0, &blob, &errors);
+ ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
+ ok(!blob, "Expected no compiled shader blob.\n");
+ ok(!!errors, "Expected non-NULL error blob.\n");
+ if (!errors)
+ return;
+
+ if (vkd3d_test_state.debug_level)
+ trace("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors));
+ ID3D10Blob_Release(errors);
+
+ shader_source_len = 0;
+ break;
+ }
+
+ case STATE_PREPROC_INVALID:
+ {
+ ID3D10Blob *blob = NULL, *errors = NULL;
+ HRESULT hr;
+
+ hr = D3DPreprocess(shader_source, strlen(shader_source), NULL, NULL, NULL, &blob, &errors);
+ ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
+ ok(!blob, "Expected no compiled shader blob.\n");
+ ok(!!errors, "Expected non-NULL error blob.\n");
+
+ if (errors)
+ {
+ if (vkd3d_test_state.debug_level)
+ trace("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors));
+ ID3D10Blob_Release(errors);
+ }
+
+ shader_source_len = 0;
+ break;
+ }
+
+ case STATE_PREPROC:
+ {
+ ID3D10Blob *blob = NULL, *errors = NULL;
+ SIZE_T size;
+ HRESULT hr;
+ char *text;
+
+ hr = D3DPreprocess(shader_source, strlen(shader_source), NULL, NULL, NULL, &blob, &errors);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+ if (hr == S_OK)
+ {
+ if (errors)
+ {
+ if (vkd3d_test_state.debug_level)
+ trace("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors));
+ ID3D10Blob_Release(errors);
+ }
+
+ text = ID3D10Blob_GetBufferPointer(blob);
+ size = ID3D10Blob_GetBufferSize(blob);
+ ok(vkd3d_memmem(text, size, "pass", strlen("pass")),
+ "'pass' not found in preprocessed shader.\n");
+ ok(!vkd3d_memmem(text, size, "fail", strlen("fail")),
+ "'fail' found in preprocessed shader.\n");
+ ID3D10Blob_Release(blob);
+ }
+
+ shader_source_len = 0;
+ break;
+ }
+ }
+ }
+
+ if (!ret)
+ break;
+
+ if (line[0] == '[')
+ {
+ unsigned int index;
+
+ if (!strcmp(line, "[pixel shader]\n"))
+ {
+ state = STATE_SHADER_PIXEL;
+
+ if (context.ps_code)
+ ID3D10Blob_Release(context.ps_code);
+ context.ps_code = NULL;
+ }
+ else if (!strcmp(line, "[pixel shader fail]\n"))
+ {
+ state = STATE_SHADER_INVALID_PIXEL;
+ }
+ else if (sscanf(line, "[sampler %u]\n", &index))
+ {
+ state = STATE_SAMPLER;
+
+ if ((current_sampler = get_sampler(&context, index)))
+ {
+ memset(current_sampler, 0, sizeof(*current_sampler));
+ }
+ else
+ {
+ context.samplers = realloc(context.samplers,
+ ++context.sampler_count * sizeof(*context.samplers));
+ current_sampler = &context.samplers[context.sampler_count - 1];
+ memset(current_sampler, 0, sizeof(*current_sampler));
+ }
+ current_sampler->slot = index;
+ current_sampler->filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
+ current_sampler->u_address = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
+ current_sampler->v_address = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
+ current_sampler->w_address = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
+ }
+ else if (sscanf(line, "[texture %u]\n", &index))
+ {
+ state = STATE_TEXTURE;
+
+ if ((current_texture = get_texture(&context, index)))
+ {
+ free_texture(current_texture);
+ }
+ else
+ {
+ context.textures = realloc(context.textures,
+ ++context.texture_count * sizeof(*context.textures));
+ current_texture = &context.textures[context.texture_count - 1];
+ memset(current_texture, 0, sizeof(*current_texture));
+ }
+ current_texture->slot = index;
+ current_texture->format = DXGI_FORMAT_R32G32B32A32_FLOAT;
+ current_texture->data_type = TEXTURE_DATA_FLOAT;
+ current_texture->texel_size = 16;
+ }
+ else if (!strcmp(line, "[test]\n"))
+ {
+ state = STATE_TEST;
+ }
+ else if (!strcmp(line, "[preproc]\n"))
+ {
+ state = STATE_PREPROC;
+ }
+ else if (!strcmp(line, "[preproc fail]\n"))
+ {
+ state = STATE_PREPROC_INVALID;
+ }
+
+ vkd3d_test_set_context("Section %.*s, line %u", strlen(line) - 1, line, line_number);
+ }
+ else if (line[0] != '%' && line[0] != '\n')
+ {
+ switch (state)
+ {
+ case STATE_NONE:
+ fatal_error("Malformed line '%s'.\n", line);
+ break;
+
+ case STATE_PREPROC:
+ case STATE_PREPROC_INVALID:
+ case STATE_SHADER_INVALID_PIXEL:
+ case STATE_SHADER_PIXEL:
+ {
+ size_t len = strlen(line);
+
+ vkd3d_array_reserve((void **)&shader_source, &shader_source_size, shader_source_len + len + 1, 1);
+ memcpy(shader_source + shader_source_len, line, len + 1);
+ shader_source_len += len;
+ break;
+ }
+
+ case STATE_SAMPLER:
+ parse_sampler_directive(current_sampler, line);
+ break;
+
+ case STATE_TEXTURE:
+ parse_texture_directive(current_texture, line);
+ break;
+
+ case STATE_TEST:
+ parse_test_directive(&context, line);
+ break;
+ }
+ }
+ }
+
+ if (context.ps_code)
+ ID3D10Blob_Release(context.ps_code);
+ for (i = 0; i < context.texture_count; ++i)
+ free_texture(&context.textures[i]);
+ destroy_test_context(&context.c);
+
+ fclose(f);
+}
+
+START_TEST(shader_runner)
+{
+ run_shader_tests_d3d12(argc, argv);
+}
diff --git a/tests/shader_runner.h b/tests/shader_runner.h
new file mode 100644
index 000000000..5178c6544
--- /dev/null
+++ b/tests/shader_runner.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 Zebediah Figura for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "vkd3d_windows.h"
+#include "vkd3d_d3dcommon.h"
+
+struct shader_runner_ops
+{
+ ID3D10Blob *(*compile_shader)(const char *source);
+};
+
+void run_shader_tests(int argc, char **argv, const struct shader_runner_ops *ops);
+
+void run_shader_tests_d3d12(int argc, char **argv);
diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c
index 47f419b96..6246c8701 100644
--- a/tests/shader_runner_d3d12.c
+++ b/tests/shader_runner_d3d12.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 Zebediah Figura for CodeWeavers
+ * Copyright 2020-2021 Zebediah Figura for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -16,127 +16,21 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-/*
- * This application contains code derived from piglit, the license for which
- * follows:
- *
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include "d3d12_crosstest.h"
-#include <errno.h>
-
-static void VKD3D_NORETURN VKD3D_PRINTF_FUNC(1, 2) fatal_error(const char *format, ...)
-{
- va_list args;
-
- va_start(args, format);
- vfprintf(stderr, format, args);
- va_end(args);
- exit(1);
-}
-
-static bool vkd3d_array_reserve(void **elements, size_t *capacity, size_t element_count, size_t element_size)
-{
- size_t new_capacity, max_capacity;
- void *new_elements;
-
- if (element_count <= *capacity)
- return true;
-
- max_capacity = ~(size_t)0 / element_size;
- if (max_capacity < element_count)
- return false;
-
- new_capacity = max(*capacity, 4);
- while (new_capacity < element_count && new_capacity <= max_capacity / 2)
- new_capacity *= 2;
-
- if (new_capacity < element_count)
- new_capacity = element_count;
-
- if (!(new_elements = realloc(*elements, new_capacity * element_size)))
- return false;
-
- *elements = new_elements;
- *capacity = new_capacity;
-
- return true;
-}
-
-enum texture_data_type
-{
- TEXTURE_DATA_FLOAT,
- TEXTURE_DATA_SINT,
- TEXTURE_DATA_UINT,
-};
+#define COBJMACROS
+#define CONST_VTABLE
+#define VKD3D_TEST_NO_DEFS
+#include "vkd3d_windows.h"
+#include "vkd3d_d3dcommon.h"
+#include "vkd3d_d3dcompiler.h"
+#include "vkd3d_test.h"
+#include "shader_runner.h"
-struct sampler
-{
- unsigned int slot;
-
- D3D12_FILTER filter;
- D3D12_TEXTURE_ADDRESS_MODE u_address, v_address, w_address;
-};
-
-struct texture
-{
- unsigned int slot;
-
- DXGI_FORMAT format;
- enum texture_data_type data_type;
- unsigned int texel_size;
- unsigned int width, height;
- uint8_t *data;
- size_t data_size, data_capacity;
-
- D3D12_DESCRIPTOR_RANGE descriptor_range;
- ID3D12DescriptorHeap *heap;
- ID3D12Resource *resource;
- unsigned int root_index;
-};
-
-struct shader_context
-{
- struct test_context c;
-
- ID3D10Blob *ps_code;
-
- uint32_t *uniforms;
- size_t uniform_count;
-
- struct texture *textures;
- size_t texture_count;
-
- struct sampler *samplers;
- size_t sampler_count;
-};
-
-static ID3D10Blob *compile_shader(const char *source, const char *target)
+static ID3D10Blob *d3d12_runner_compile_shader(const char *source)
{
ID3D10Blob *blob = NULL, *errors = NULL;
HRESULT hr;
- hr = D3DCompile(source, strlen(source), NULL, NULL, NULL, "main", target, 0, 0, &blob, &errors);
+ hr = D3DCompile(source, strlen(source), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &blob, &errors);
ok(hr == S_OK, "Failed to compile shader, hr %#x.\n", hr);
if (errors)
{
@@ -147,723 +41,12 @@ static ID3D10Blob *compile_shader(const char *source, const char *target)
return blob;
}
-static void free_texture(struct texture *texture)
+static const struct shader_runner_ops d3d12_runner_ops =
{
- ID3D12DescriptorHeap_Release(texture->heap);
- ID3D12Resource_Release(texture->resource);
- free(texture->data);
- memset(texture, 0, sizeof(*texture));
-}
-
-enum parse_state
-{
- STATE_NONE,
- STATE_PREPROC,
- STATE_PREPROC_INVALID,
- STATE_SAMPLER,
- STATE_SHADER_INVALID_PIXEL,
- STATE_SHADER_PIXEL,
- STATE_TEXTURE,
- STATE_TEST,
+ .compile_shader = d3d12_runner_compile_shader,
};
-static bool match_string(const char *line, const char *token, const char **const rest)
-{
- size_t len = strlen(token);
-
- if (strncmp(line, token, len) || !isspace(line[len]))
- return false;
- if (rest)
- {
- *rest = line + len;
- while (isspace(**rest))
- ++*rest;
- }
- return true;
-}
-
-static void parse_texture_format(struct texture *texture, const char *line)
-{
- static const struct
- {
- const char *string;
- enum texture_data_type data_type;
- unsigned int texel_size;
- DXGI_FORMAT format;
- }
- formats[] =
- {
- {"r32g32b32a32 float", TEXTURE_DATA_FLOAT, 16, DXGI_FORMAT_R32G32B32A32_FLOAT},
- {"r32g32 uint", TEXTURE_DATA_UINT, 8, DXGI_FORMAT_R32G32_UINT},
- {"r32 float", TEXTURE_DATA_FLOAT, 4, DXGI_FORMAT_R32_FLOAT},
- {"r32 sint", TEXTURE_DATA_SINT, 4, DXGI_FORMAT_R32_SINT},
- };
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(formats); ++i)
- {
- if (match_string(line, formats[i].string, &line))
- {
- texture->format = formats[i].format;
- texture->data_type = formats[i].data_type;
- texture->texel_size = formats[i].texel_size;
- return;
- }
- }
-
- fatal_error("Unknown format '%s'.\n", line);
-}
-
-static D3D12_TEXTURE_ADDRESS_MODE parse_sampler_address_mode(const char *line, const char **rest)
-{
- if (match_string(line, "border", rest))
- return D3D12_TEXTURE_ADDRESS_MODE_BORDER;
- if (match_string(line, "clamp", rest))
- return D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
- if (match_string(line, "mirror_once", rest))
- return D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE;
- if (match_string(line, "mirror", rest))
- return D3D12_TEXTURE_ADDRESS_MODE_MIRROR;
- if (match_string(line, "wrap", rest))
- return D3D12_TEXTURE_ADDRESS_MODE_WRAP;
-
- fatal_error("Unknown sampler address mode '%s'.\n", line);
-}
-
-static void parse_sampler_directive(struct sampler *sampler, const char *line)
-{
- if (match_string(line, "address", &line))
- {
- sampler->u_address = parse_sampler_address_mode(line, &line);
- sampler->v_address = parse_sampler_address_mode(line, &line);
- sampler->w_address = parse_sampler_address_mode(line, &line);
- }
- else if (match_string(line, "filter", &line))
- {
- static const struct
- {
- const char *string;
- D3D12_FILTER filter;
- }
- filters[] =
- {
- {"point point point", D3D12_FILTER_MIN_MAG_MIP_POINT},
- {"point point linear", D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR},
- {"point linear point", D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT},
- {"point linear linear", D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR},
- {"linear point point", D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT},
- {"linear point linear", D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR},
- {"linear linear point", D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT},
- {"linear linear linear", D3D12_FILTER_MIN_MAG_MIP_LINEAR},
- };
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(filters); ++i)
- {
- if (match_string(line, filters[i].string, &line))
- {
- sampler->filter = filters[i].filter;
- return;
- }
- }
-
- fatal_error("Unknown sampler filter '%s'.\n", line);
- }
- else
- {
- fatal_error("Unknown sampler directive '%s'.\n", line);
- }
-}
-
-static void parse_texture_directive(struct texture *texture, const char *line)
-{
- int ret;
-
- if (match_string(line, "format", &line))
- {
- parse_texture_format(texture, line);
- }
- else if (match_string(line, "size", &line))
- {
- ret = sscanf(line, "( %u , %u )", &texture->width, &texture->height);
- if (ret < 2)
- fatal_error("Malformed texture size '%s'.\n", line);
- }
- else
- {
- union
- {
- float f;
- int32_t i;
- uint32_t u;
- } u;
- char *rest;
-
- u.u = 0;
-
- for (;;)
- {
- switch (texture->data_type)
- {
- case TEXTURE_DATA_FLOAT:
- u.f = strtof(line, &rest);
- break;
-
- case TEXTURE_DATA_SINT:
- u.i = strtol(line, &rest, 10);
- break;
-
- case TEXTURE_DATA_UINT:
- u.u = strtoul(line, &rest, 10);
- break;
- }
-
- if (rest == line)
- break;
-
- vkd3d_array_reserve((void **)&texture->data, &texture->data_capacity, texture->data_size + sizeof(u), 1);
- memcpy(texture->data + texture->data_size, &u, sizeof(u));
- texture->data_size += sizeof(u);
- line = rest;
- }
- }
-}
-
-static void parse_test_directive(struct shader_context *context, const char *line)
-{
- if (match_string(line, "draw quad", &line))
- {
- D3D12_SHADER_BYTECODE ps
- = {ID3D10Blob_GetBufferPointer(context->ps_code), ID3D10Blob_GetBufferSize(context->ps_code)};
- ID3D12GraphicsCommandList *command_list = context->c.list;
- D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {0};
- D3D12_ROOT_PARAMETER root_params[3], *root_param;
- D3D12_STATIC_SAMPLER_DESC static_samplers[1];
- static const float clear_color[4];
- unsigned int uniform_index;
- ID3D12PipelineState *pso;
- HRESULT hr;
- size_t i;
-
- root_signature_desc.NumParameters = 0;
- root_signature_desc.pParameters = root_params;
- root_signature_desc.NumStaticSamplers = 0;
- root_signature_desc.pStaticSamplers = static_samplers;
-
- if (context->uniform_count)
- {
- uniform_index = root_signature_desc.NumParameters++;
- root_param = &root_params[uniform_index];
- root_param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
- root_param->Constants.ShaderRegister = 0;
- root_param->Constants.RegisterSpace = 0;
- root_param->Constants.Num32BitValues = context->uniform_count;
- root_param->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
- }
-
- for (i = 0; i < context->texture_count; ++i)
- {
- struct texture *texture = &context->textures[i];
- D3D12_DESCRIPTOR_RANGE *range = &texture->descriptor_range;
- D3D12_SUBRESOURCE_DATA resource_data;
-
- texture->root_index = root_signature_desc.NumParameters++;
- root_param = &root_params[texture->root_index];
- root_param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- root_param->DescriptorTable.NumDescriptorRanges = 1;
- root_param->DescriptorTable.pDescriptorRanges = range;
- root_param->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
-
- range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
- range->NumDescriptors = 1;
- range->BaseShaderRegister = texture->slot;
- range->RegisterSpace = 0;
- range->OffsetInDescriptorsFromTableStart = 0;
-
- if (!texture->resource)
- {
- texture->heap = create_gpu_descriptor_heap(context->c.device,
- D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1);
- texture->resource = create_default_texture(context->c.device, texture->width, texture->height,
- texture->format, 0, D3D12_RESOURCE_STATE_COPY_DEST);
- resource_data.pData = texture->data;
- resource_data.SlicePitch = resource_data.RowPitch = texture->width * texture->texel_size;
- upload_texture_data(texture->resource, &resource_data, 1, context->c.queue, command_list);
- reset_command_list(command_list, context->c.allocator);
- transition_resource_state(command_list, texture->resource, D3D12_RESOURCE_STATE_COPY_DEST,
- D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
- ID3D12Device_CreateShaderResourceView(context->c.device, texture->resource,
- NULL, get_cpu_descriptor_handle(&context->c, texture->heap, 0));
- }
- }
-
- assert(root_signature_desc.NumParameters <= ARRAY_SIZE(root_params));
-
- for (i = 0; i < context->sampler_count; ++i)
- {
- D3D12_STATIC_SAMPLER_DESC *sampler_desc = &static_samplers[root_signature_desc.NumStaticSamplers++];
- const struct sampler *sampler = &context->samplers[i];
-
- memset(sampler_desc, 0, sizeof(*sampler_desc));
- sampler_desc->Filter = sampler->filter;
- sampler_desc->AddressU = sampler->u_address;
- sampler_desc->AddressV = sampler->v_address;
- sampler_desc->AddressW = sampler->w_address;
- sampler_desc->ShaderRegister = sampler->slot;
- sampler_desc->RegisterSpace = 0;
- sampler_desc->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
- }
-
- if (context->c.root_signature)
- ID3D12RootSignature_Release(context->c.root_signature);
- hr = create_root_signature(context->c.device, &root_signature_desc, &context->c.root_signature);
- ok(hr == S_OK, "Failed to create root signature, hr %#x.\n", hr);
-
- pso = create_pipeline_state(context->c.device, context->c.root_signature, context->c.render_target_desc.Format,
- NULL, &ps, NULL);
- if (!pso)
- return;
- vkd3d_array_reserve((void **)&context->c.pso, &context->c.pso_capacity, context->c.pso_count + 1, sizeof(*context->c.pso));
- context->c.pso[context->c.pso_count++] = pso;
-
- ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context->c.root_signature);
- if (context->uniform_count)
- ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(command_list, uniform_index,
- context->uniform_count, context->uniforms, 0);
- for (i = 0; i < context->texture_count; ++i)
- ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, context->textures[i].root_index,
- get_gpu_descriptor_handle(&context->c, context->textures[i].heap, 0));
-
- ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &context->c.rtv, false, NULL);
- ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &context->c.scissor_rect);
- ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &context->c.viewport);
- ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
- ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, context->c.rtv, clear_color, 0, NULL);
- ID3D12GraphicsCommandList_SetPipelineState(command_list, pso);
- ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0);
- transition_resource_state(command_list, context->c.render_target,
- D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE);
- }
- else if (match_string(line, "probe all rgba", &line))
- {
- unsigned int ulps;
- struct vec4 v;
- int ret;
-
- ret = sscanf(line, "( %f , %f , %f , %f ) %u", &v.x, &v.y, &v.z, &v.w, &ulps);
- if (ret < 4)
- fatal_error("Malformed probe arguments '%s'.\n", line);
- if (ret < 5)
- ulps = 0;
- check_sub_resource_vec4(context->c.render_target, 0, context->c.queue, context->c.list, &v, ulps);
- reset_command_list(context->c.list, context->c.allocator);
- }
- else if (match_string(line, "probe rect rgba", &line))
- {
- unsigned int x, y, w, h, ulps;
- struct resource_readback rb;
- struct vec4 v;
- RECT rect;
- int ret;
-
- ret = sscanf(line, "( %u , %u , %u , %u ) ( %f , %f , %f , %f ) %u",
- &x, &y, &w, &h, &v.x, &v.y, &v.z, &v.w, &ulps);
- if (ret < 8)
- fatal_error("Malformed probe arguments '%s'.\n", line);
- if (ret < 9)
- ulps = 0;
-
- get_texture_readback_with_command_list(context->c.render_target, 0, &rb, context->c.queue, context->c.list);
- rect.left = x;
- rect.right = x + w;
- rect.top = y;
- rect.bottom = y + h;
- check_readback_data_vec4(&rb, &rect, &v, ulps);
- release_resource_readback(&rb);
- reset_command_list(context->c.list, context->c.allocator);
- }
- else if (match_string(line, "probe rgba", &line))
- {
- struct resource_readback rb;
- unsigned int x, y, ulps;
- struct vec4 v;
- RECT rect;
- int ret;
-
- ret = sscanf(line, "( %u , %u ) ( %f , %f , %f , %f ) %u", &x, &y, &v.x, &v.y, &v.z, &v.w, &ulps);
- if (ret < 6)
- fatal_error("Malformed probe arguments '%s'.\n", line);
- if (ret < 7)
- ulps = 0;
-
- get_texture_readback_with_command_list(context->c.render_target, 0, &rb, context->c.queue, context->c.list);
- rect.left = x;
- rect.right = x + 1;
- rect.top = y;
- rect.bottom = y + 1;
- check_readback_data_vec4(&rb, &rect, &v, ulps);
- release_resource_readback(&rb);
- reset_command_list(context->c.list, context->c.allocator);
- }
- else if (match_string(line, "uniform", &line))
- {
- unsigned int offset;
-
- if (!sscanf(line, "%u", &offset))
- fatal_error("Unknown uniform type '%s'.\n", line);
- line = strchr(line, ' ') + 1;
-
- if (match_string(line, "float4", &line))
- {
- struct vec4 v;
-
- if (sscanf(line, "%f %f %f %f", &v.x, &v.y, &v.z, &v.w) < 4)
- fatal_error("Malformed float4 constant '%s'.\n", line);
- if (offset + 4 > context->uniform_count)
- {
- context->uniform_count = offset + 4;
- context->uniforms = realloc(context->uniforms, context->uniform_count * sizeof(*context->uniforms));
- }
- memcpy(context->uniforms + offset, &v, sizeof(v));
- }
- else if (match_string(line, "float", &line))
- {
- float f;
-
- if (sscanf(line, "%f", &f) < 1)
- fatal_error("Malformed float constant '%s'.\n", line);
- if (offset + 1 > context->uniform_count)
- {
- context->uniform_count = offset + 1;
- context->uniforms = realloc(context->uniforms, context->uniform_count * sizeof(*context->uniforms));
- }
- memcpy(context->uniforms + offset, &f, sizeof(f));
- }
- else if (match_string(line, "int", &line))
- {
- int i;
-
- if (sscanf(line, "%i", &i) < 1)
- fatal_error("Malformed int constant '%s'.\n", line);
- if (offset + 1 > context->uniform_count)
- {
- context->uniform_count = offset + 1;
- context->uniforms = realloc(context->uniforms, context->uniform_count * sizeof(*context->uniforms));
- }
- memcpy(context->uniforms + offset, &i, sizeof(i));
- }
- else if (match_string(line, "uint", &line))
- {
- unsigned int u;
-
- if (sscanf(line, "%u", &u) < 1)
- fatal_error("Malformed uint constant '%s'.\n", line);
- if (offset + 1 > context->uniform_count)
- {
- context->uniform_count = offset + 1;
- context->uniforms = realloc(context->uniforms, context->uniform_count * sizeof(*context->uniforms));
- }
- memcpy(context->uniforms + offset, &u, sizeof(u));
- }
- }
- else
- {
- fatal_error("Unknown test directive '%s'.\n", line);
- }
-}
-
-static struct sampler *get_sampler(struct shader_context *context, unsigned int slot)
-{
- struct sampler *sampler;
- size_t i;
-
- for (i = 0; i < context->sampler_count; ++i)
- {
- sampler = &context->samplers[i];
-
- if (sampler->slot == slot)
- return sampler;
- }
-
- return NULL;
-}
-
-static struct texture *get_texture(struct shader_context *context, unsigned int slot)
-{
- struct texture *texture;
- size_t i;
-
- for (i = 0; i < context->texture_count; ++i)
- {
- texture = &context->textures[i];
- if (texture->slot == slot)
- return texture;
- }
-
- return NULL;
-}
-
-START_TEST(shader_runner_d3d12)
+void run_shader_tests_d3d12(int argc, char **argv)
{
- static const struct test_context_desc desc =
- {
- .rt_width = 640,
- .rt_height = 480,
- .no_root_signature = true,
- .rt_format = DXGI_FORMAT_R32G32B32A32_FLOAT,
- };
- size_t shader_source_size = 0, shader_source_len = 0;
- struct sampler *current_sampler = NULL;
- struct texture *current_texture = NULL;
- enum parse_state state = STATE_NONE;
- unsigned int i, line_number = 0;
- struct shader_context context;
- const char *filename = NULL;
- char *shader_source = NULL;
- char line[256];
- FILE *f;
-
- parse_args(argc, argv);
- enable_d3d12_debug_layer(argc, argv);
- init_adapter_info();
-
- for (i = 1; i < argc; ++i)
- {
- if (argv[i][0] != '-')
- {
- filename = argv[i];
- break;
- }
- }
-
- if (!filename)
- {
- fprintf(stderr, "Usage: %s [file]\n", argv[0]);
- return;
- }
-
- if (!(f = fopen(filename, "r")))
- {
- fatal_error("Unable to open '%s' for reading: %s\n", argv[1], strerror(errno));
- return;
- }
-
- memset(&context, 0, sizeof(context));
- init_test_context(&context.c, &desc);
-
- for (;;)
- {
- char *ret = fgets(line, sizeof(line), f);
-
- ++line_number;
-
- if (!ret || line[0] == '[')
- {
- switch (state)
- {
- case STATE_NONE:
- case STATE_SAMPLER:
- case STATE_TEST:
- case STATE_TEXTURE:
- break;
-
- case STATE_SHADER_PIXEL:
- if (!(context.ps_code = compile_shader(shader_source, "ps_4_0")))
- return;
- shader_source_len = 0;
- break;
-
- case STATE_SHADER_INVALID_PIXEL:
- {
- ID3D10Blob *blob = NULL, *errors = NULL;
- HRESULT hr;
-
- hr = D3DCompile(shader_source, strlen(shader_source), NULL,
- NULL, NULL, "main", "ps_4_0", 0, 0, &blob, &errors);
- ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
- ok(!blob, "Expected no compiled shader blob.\n");
- ok(!!errors, "Expected non-NULL error blob.\n");
- if (!errors)
- return;
-
- if (vkd3d_test_state.debug_level)
- trace("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors));
- ID3D10Blob_Release(errors);
-
- shader_source_len = 0;
- break;
- }
-
- case STATE_PREPROC_INVALID:
- {
- ID3D10Blob *blob = NULL, *errors = NULL;
- HRESULT hr;
-
- hr = D3DPreprocess(shader_source, strlen(shader_source), NULL, NULL, NULL, &blob, &errors);
- ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
- ok(!blob, "Expected no compiled shader blob.\n");
- ok(!!errors, "Expected non-NULL error blob.\n");
-
- if (errors)
- {
- if (vkd3d_test_state.debug_level)
- trace("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors));
- ID3D10Blob_Release(errors);
- }
-
- shader_source_len = 0;
- break;
- }
-
- case STATE_PREPROC:
- {
- ID3D10Blob *blob = NULL, *errors = NULL;
- SIZE_T size;
- HRESULT hr;
- char *text;
-
- hr = D3DPreprocess(shader_source, strlen(shader_source), NULL, NULL, NULL, &blob, &errors);
- ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
- if (hr == S_OK)
- {
- if (errors)
- {
- if (vkd3d_test_state.debug_level)
- trace("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors));
- ID3D10Blob_Release(errors);
- }
-
- text = ID3D10Blob_GetBufferPointer(blob);
- size = ID3D10Blob_GetBufferSize(blob);
- ok(vkd3d_memmem(text, size, "pass", strlen("pass")),
- "'pass' not found in preprocessed shader.\n");
- ok(!vkd3d_memmem(text, size, "fail", strlen("fail")),
- "'fail' found in preprocessed shader.\n");
- ID3D10Blob_Release(blob);
- }
-
- shader_source_len = 0;
- break;
- }
- }
- }
-
- if (!ret)
- break;
-
- if (line[0] == '[')
- {
- unsigned int index;
-
- if (!strcmp(line, "[pixel shader]\n"))
- {
- state = STATE_SHADER_PIXEL;
-
- if (context.ps_code)
- ID3D10Blob_Release(context.ps_code);
- context.ps_code = NULL;
- }
- else if (!strcmp(line, "[pixel shader fail]\n"))
- {
- state = STATE_SHADER_INVALID_PIXEL;
- }
- else if (sscanf(line, "[sampler %u]\n", &index))
- {
- state = STATE_SAMPLER;
-
- if ((current_sampler = get_sampler(&context, index)))
- {
- memset(current_sampler, 0, sizeof(*current_sampler));
- }
- else
- {
- context.samplers = realloc(context.samplers,
- ++context.sampler_count * sizeof(*context.samplers));
- current_sampler = &context.samplers[context.sampler_count - 1];
- memset(current_sampler, 0, sizeof(*current_sampler));
- }
- current_sampler->slot = index;
- current_sampler->filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
- current_sampler->u_address = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
- current_sampler->v_address = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
- current_sampler->w_address = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
- }
- else if (sscanf(line, "[texture %u]\n", &index))
- {
- state = STATE_TEXTURE;
-
- if ((current_texture = get_texture(&context, index)))
- {
- free_texture(current_texture);
- }
- else
- {
- context.textures = realloc(context.textures,
- ++context.texture_count * sizeof(*context.textures));
- current_texture = &context.textures[context.texture_count - 1];
- memset(current_texture, 0, sizeof(*current_texture));
- }
- current_texture->slot = index;
- current_texture->format = DXGI_FORMAT_R32G32B32A32_FLOAT;
- current_texture->data_type = TEXTURE_DATA_FLOAT;
- current_texture->texel_size = 16;
- }
- else if (!strcmp(line, "[test]\n"))
- {
- state = STATE_TEST;
- }
- else if (!strcmp(line, "[preproc]\n"))
- {
- state = STATE_PREPROC;
- }
- else if (!strcmp(line, "[preproc fail]\n"))
- {
- state = STATE_PREPROC_INVALID;
- }
-
- vkd3d_test_set_context("Section %.*s, line %u", strlen(line) - 1, line, line_number);
- }
- else if (line[0] != '%' && line[0] != '\n')
- {
- switch (state)
- {
- case STATE_NONE:
- fatal_error("Malformed line '%s'.\n", line);
- break;
-
- case STATE_PREPROC:
- case STATE_PREPROC_INVALID:
- case STATE_SHADER_INVALID_PIXEL:
- case STATE_SHADER_PIXEL:
- {
- size_t len = strlen(line);
-
- vkd3d_array_reserve((void **)&shader_source, &shader_source_size, shader_source_len + len + 1, 1);
- memcpy(shader_source + shader_source_len, line, len + 1);
- shader_source_len += len;
- break;
- }
-
- case STATE_SAMPLER:
- parse_sampler_directive(current_sampler, line);
- break;
-
- case STATE_TEXTURE:
- parse_texture_directive(current_texture, line);
- break;
-
- case STATE_TEST:
- parse_test_directive(&context, line);
- break;
- }
- }
- }
-
- if (context.ps_code)
- ID3D10Blob_Release(context.ps_code);
- for (i = 0; i < context.texture_count; ++i)
- free_texture(&context.textures[i]);
- destroy_test_context(&context.c);
-
- fclose(f);
+ run_shader_tests(argc, argv, &d3d12_runner_ops);
}
--
2.34.1
3
8
Re: [Mingw-w64-public] [PATCH] wtypes.h: replace #include <...> with #include "..." for rpc
by LIU Hao 17 Jan '22
by LIU Hao 17 Jan '22
17 Jan '22
在 1/13/22 10:07 PM, Jonathan Marler 写道:
> Been 3 months since my last email, what's going on with this?
>
> On Tue, Oct 19, 2021 at 11:03 PM Jonathan Marler <johnnymarler(a)gmail.com>
> wrote:
>
>> Jacek were you able to forward this discussion to Wine? If so do you have
>> a link to that discussion? Thanks.
>>
>>
This patch applies to a file that is directly copied from wine; any changes will be overwritten.
Thus it will not be accepted.
I'm adding wine as CC now. The original thread is located at
https://sourceforge.net/p/mingw-w64/mailman/message/37341200/.
--
Best regards,
LIU Hao
2
1
[PATCH vkd3d] vkd3d-shader/spirv: Enable descriptor indexing if runtime arrays are used.
by Conor McCarthy 17 Jan '22
by Conor McCarthy 17 Jan '22
17 Jan '22
SpvCapabilityRuntimeDescriptorArrayEXT requires descriptor indexing and
a validation error will result if it is not enabled.
Signed-off-by: Conor McCarthy <cmccarthy(a)codeweavers.com>
---
libs/vkd3d-shader/spirv.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c
index fa3ca67e..1ffce6a1 100644
--- a/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d-shader/spirv.c
@@ -1833,7 +1833,8 @@ static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder,
vkd3d_spirv_build_op_extension(&stream, "SPV_KHR_shader_draw_parameters");
if (vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityDemoteToHelperInvocationEXT))
vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_demote_to_helper_invocation");
- if (vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityUniformBufferArrayDynamicIndexing)
+ if (vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityRuntimeDescriptorArrayEXT)
+ || vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityUniformBufferArrayDynamicIndexing)
|| vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT)
|| vkd3d_spirv_capability_is_enabled(builder, SpvCapabilitySampledImageArrayDynamicIndexing)
|| vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityStorageBufferArrayDynamicIndexing)
--
2.34.1
2
1
[PATCH vkd3d v2] vkd3d: Implement ID3D12CommandQueue_GetClockCalibration().
by Conor McCarthy 17 Jan '22
by Conor McCarthy 17 Jan '22
17 Jan '22
Extends vkd3d_instance_create_info with struct vkd3d_host_time_domain_info
to allow host ticks per second to be changed from the default 10000000.
Signed-off-by: Conor McCarthy <cmccarthy(a)codeweavers.com>
---
v2: Do not use a Vk MAX_ENUM value, rearrange a conditional to avoid
indentation, use a loop to select host time domain, and introduce an
optional instance parameter for host ticks per second.
---
include/vkd3d.h | 12 +++++++
libs/vkd3d/command.c | 59 +++++++++++++++++++++++++++++--
libs/vkd3d/device.c | 71 ++++++++++++++++++++++++++++++++++++++
libs/vkd3d/vkd3d_private.h | 4 +++
libs/vkd3d/vulkan_procs.h | 6 ++++
tests/d3d12.c | 4 ---
6 files changed, 150 insertions(+), 6 deletions(-)
diff --git a/include/vkd3d.h b/include/vkd3d.h
index 61ccf6c3..a2c70116 100644
--- a/include/vkd3d.h
+++ b/include/vkd3d.h
@@ -48,6 +48,9 @@ enum vkd3d_structure_type
VKD3D_STRUCTURE_TYPE_OPTIONAL_DEVICE_EXTENSIONS_INFO,
VKD3D_STRUCTURE_TYPE_APPLICATION_INFO,
+ /* 1.3 */
+ VKD3D_STRUCTURE_TYPE_HOST_TIME_DOMAIN_INFO,
+
VKD3D_FORCE_32_BIT_ENUM(VKD3D_STRUCTURE_TYPE),
};
@@ -109,6 +112,15 @@ struct vkd3d_application_info
enum vkd3d_api_version api_version;
};
+/* Extends vkd3d_instance_create_info. Available since 1.3. */
+struct vkd3d_host_time_domain_info
+{
+ enum vkd3d_structure_type type;
+ const void *next;
+
+ uint64_t ticks_per_second;
+};
+
struct vkd3d_device_create_info
{
enum vkd3d_structure_type type;
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index 3e252aee..353a61cd 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -6238,13 +6238,68 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_GetTimestampFrequency(ID3D1
return S_OK;
}
+#define NANOSECONDS_IN_A_SECOND 1000000000
+
static HRESULT STDMETHODCALLTYPE d3d12_command_queue_GetClockCalibration(ID3D12CommandQueue *iface,
UINT64 *gpu_timestamp, UINT64 *cpu_timestamp)
{
- FIXME("iface %p, gpu_timestamp %p, cpu_timestamp %p stub!\n",
+ struct d3d12_command_queue *command_queue = impl_from_ID3D12CommandQueue(iface);
+ struct d3d12_device *device = command_queue->device;
+ const struct vkd3d_vk_device_procs *vk_procs;
+ VkCalibratedTimestampInfoEXT infos[2];
+ uint64_t timestamps[2];
+ uint64_t deviations[2];
+ VkResult vr;
+
+ TRACE("iface %p, gpu_timestamp %p, cpu_timestamp %p.\n",
iface, gpu_timestamp, cpu_timestamp);
- return E_NOTIMPL;
+ if (!command_queue->vkd3d_queue->timestamp_bits)
+ {
+ WARN("Timestamp queries not supported.\n");
+ return E_FAIL;
+ }
+
+ if (!gpu_timestamp || !cpu_timestamp)
+ return E_INVALIDARG;
+
+ if (!device->vk_info.EXT_calibrated_timestamps || device->vk_host_time_domain == -1)
+ {
+ WARN(!device->vk_info.EXT_calibrated_timestamps
+ ? "VK_EXT_calibrated_timestamps was not found. Setting timestamps to zero.\n"
+ : "Device and/or host time domain is not available. Setting timestamps to zero.\n");
+ *gpu_timestamp = 0;
+ *cpu_timestamp = 0;
+ return S_OK;
+ }
+
+ vk_procs = &device->vk_procs;
+
+ infos[0].sType = VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT;
+ infos[0].pNext = NULL;
+ infos[0].timeDomain = VK_TIME_DOMAIN_DEVICE_EXT;
+ infos[1].sType = VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT;
+ infos[1].pNext = NULL;
+ infos[1].timeDomain = device->vk_host_time_domain;
+
+ if ((vr = VK_CALL(vkGetCalibratedTimestampsEXT(command_queue->device->vk_device,
+ ARRAY_SIZE(infos), infos, timestamps, deviations))) < 0)
+ {
+ WARN("Failed to get calibrated timestamps, vr %d.\n", vr);
+ return E_FAIL;
+ }
+
+ if (infos[1].timeDomain == VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
+ || infos[1].timeDomain == VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT)
+ {
+ /* Convert monotonic clock to match Wine's RtlQueryPerformanceFrequency(). */
+ timestamps[1] /= NANOSECONDS_IN_A_SECOND / device->vkd3d_instance->host_ticks_per_second;
+ }
+
+ *gpu_timestamp = timestamps[0];
+ *cpu_timestamp = timestamps[1];
+
+ return S_OK;
}
static D3D12_COMMAND_QUEUE_DESC * STDMETHODCALLTYPE d3d12_command_queue_GetDesc(ID3D12CommandQueue *iface,
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 661ca1d9..4af26074 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -130,6 +130,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] =
VK_EXTENSION(KHR_PUSH_DESCRIPTOR, KHR_push_descriptor),
VK_EXTENSION(KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE, KHR_sampler_mirror_clamp_to_edge),
/* EXT extensions */
+ VK_EXTENSION(EXT_CALIBRATED_TIMESTAMPS, EXT_calibrated_timestamps),
VK_EXTENSION(EXT_CONDITIONAL_RENDERING, EXT_conditional_rendering),
VK_EXTENSION(EXT_DEBUG_MARKER, EXT_debug_marker),
VK_EXTENSION(EXT_DEPTH_CLIP_ENABLE, EXT_depth_clip_enable),
@@ -447,12 +448,16 @@ static uint64_t vkd3d_init_config_flags(void)
return config_flags;
}
+/* TICKSPERSEC from Wine */
+#define VKD3D_DEFAULT_HOST_TICKS_PER_SECOND 10000000
+
static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance,
const struct vkd3d_instance_create_info *create_info)
{
const struct vkd3d_vk_global_procs *vk_global_procs = &instance->vk_global_procs;
const struct vkd3d_optional_instance_extensions_info *optional_extensions;
const struct vkd3d_application_info *vkd3d_application_info;
+ const struct vkd3d_host_time_domain_info *time_domain_info;
bool *user_extension_supported = NULL;
VkApplicationInfo application_info;
VkInstanceCreateInfo instance_info;
@@ -578,6 +583,11 @@ static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance,
return hr;
}
+ if ((time_domain_info = vkd3d_find_struct(create_info->next, HOST_TIME_DOMAIN_INFO)))
+ instance->host_ticks_per_second = time_domain_info->ticks_per_second;
+ else
+ instance->host_ticks_per_second = VKD3D_DEFAULT_HOST_TICKS_PER_SECOND;
+
instance->vk_instance = vk_instance;
TRACE("Created Vulkan instance %p.\n", vk_instance);
@@ -2349,6 +2359,66 @@ static void vkd3d_gpu_descriptor_allocator_cleanup(struct vkd3d_gpu_descriptor_a
pthread_mutex_destroy(&allocator->mutex);
}
+static bool have_vk_time_domain(VkTimeDomainEXT *domains, unsigned int count, VkTimeDomainEXT domain)
+{
+ unsigned int i;
+
+ for (i = 0; i < count; ++i)
+ if (domains[i] == domain)
+ return true;
+
+ return false;
+}
+
+static void vkd3d_time_domains_init(struct d3d12_device *device)
+{
+ static const VkTimeDomainEXT host_time_domains[] =
+ {
+ /* In order of preference */
+ VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT,
+ VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT,
+ VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT,
+
+ };
+ const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance->vk_procs;
+ VkTimeDomainEXT domains[8];
+ unsigned int i;
+ uint32_t count;
+ VkResult vr;
+
+ device->vk_host_time_domain = -1;
+
+ if (!device->vk_info.EXT_calibrated_timestamps)
+ return;
+
+ count = ARRAY_SIZE(domains);
+ if ((vr = VK_CALL(vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(device->vk_physical_device,
+ &count, domains))) != VK_SUCCESS && vr != VK_INCOMPLETE)
+ {
+ WARN("Failed to get calibrated time domains, vr %d.\n", vr);
+ return;
+ }
+
+ if (vr == VK_INCOMPLETE)
+ FIXME("Calibrated time domain list is incomplete.\n");
+
+ if (!have_vk_time_domain(domains, count, VK_TIME_DOMAIN_DEVICE_EXT))
+ {
+ WARN("Device time domain not found. Calibrated timestamps will not be available.\n");
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(host_time_domains); ++i)
+ {
+ if (!have_vk_time_domain(domains, count, host_time_domains[i]))
+ continue;
+ device->vk_host_time_domain = host_time_domains[i];
+ break;
+ }
+ if (device->vk_host_time_domain == -1)
+ WARN("Found no acceptable host time domain. Calibrated timestamps will not be available.\n");
+}
+
/* ID3D12Device */
static inline struct d3d12_device *impl_from_ID3D12Device(ID3D12Device *iface)
{
@@ -3910,6 +3980,7 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
vkd3d_render_pass_cache_init(&device->render_pass_cache);
vkd3d_gpu_descriptor_allocator_init(&device->gpu_descriptor_allocator);
vkd3d_gpu_va_allocator_init(&device->gpu_va_allocator);
+ vkd3d_time_domains_init(device);
for (i = 0; i < ARRAY_SIZE(device->desc_mutex); ++i)
pthread_mutex_init(&device->desc_mutex[i], NULL);
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 047f4a29..3f5ea21c 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -108,6 +108,7 @@ struct vkd3d_vulkan_info
bool KHR_push_descriptor;
bool KHR_sampler_mirror_clamp_to_edge;
/* EXT device extensions */
+ bool EXT_calibrated_timestamps;
bool EXT_conditional_rendering;
bool EXT_debug_marker;
bool EXT_depth_clip_enable;
@@ -159,6 +160,8 @@ struct vkd3d_instance
VkDebugReportCallbackEXT vk_debug_callback;
+ uint64_t host_ticks_per_second;
+
LONG refcount;
};
@@ -1195,6 +1198,7 @@ struct d3d12_device
struct vkd3d_queue *copy_queue;
uint32_t queue_family_indices[VKD3D_MAX_QUEUE_FAMILY_COUNT];
unsigned int queue_family_count;
+ VkTimeDomainEXT vk_host_time_domain;
struct vkd3d_instance *vkd3d_instance;
diff --git a/libs/vkd3d/vulkan_procs.h b/libs/vkd3d/vulkan_procs.h
index ec29eb45..60556735 100644
--- a/libs/vkd3d/vulkan_procs.h
+++ b/libs/vkd3d/vulkan_procs.h
@@ -55,6 +55,9 @@ VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceProperties2KHR)
VK_INSTANCE_EXT_PFN(vkCreateDebugReportCallbackEXT)
VK_INSTANCE_EXT_PFN(vkDestroyDebugReportCallbackEXT)
+/* VK_EXT_calibrated_timestamps */
+VK_INSTANCE_EXT_PFN(vkGetPhysicalDeviceCalibrateableTimeDomainsEXT)
+
/* Device functions (obtained by vkGetDeviceProcAddr). */
VK_DEVICE_PFN(vkDestroyDevice) /* Load vkDestroyDevice() first. */
VK_DEVICE_PFN(vkAllocateCommandBuffers)
@@ -192,6 +195,9 @@ VK_DEVICE_EXT_PFN(vkGetDescriptorSetLayoutSupportKHR)
/* VK_KHR_push_descriptor */
VK_DEVICE_EXT_PFN(vkCmdPushDescriptorSetKHR)
+/* VK_EXT_calibrated_timestamps */
+VK_DEVICE_EXT_PFN(vkGetCalibratedTimestampsEXT)
+
/* VK_EXT_conditional_rendering */
VK_DEVICE_EXT_PFN(vkCmdBeginConditionalRenderingEXT)
VK_DEVICE_EXT_PFN(vkCmdEndConditionalRenderingEXT)
diff --git a/tests/d3d12.c b/tests/d3d12.c
index 9d4fb7d4..a4488017 100644
--- a/tests/d3d12.c
+++ b/tests/d3d12.c
@@ -36023,19 +36023,15 @@ static void test_clock_calibration(void)
return;
hr = ID3D12CommandQueue_GetClockCalibration(context.queue, &gpu_times[0], &cpu_times[0]);
- todo
ok(hr == S_OK, "Failed to retrieve calibrated timestamps, hr %#x.\n", hr);
vkd3d_sleep(100);
hr = ID3D12CommandQueue_GetClockCalibration(context.queue, &gpu_times[1], &cpu_times[1]);
- todo
ok(hr == S_OK, "Failed to retrieve calibrated timestamps, hr %#x.\n", hr);
- todo
ok(gpu_times[1] > gpu_times[0], "Inconsistent GPU timestamps %"PRIu64" and %"PRIu64".\n",
gpu_times[0], gpu_times[1]);
- todo
ok(cpu_times[1] > cpu_times[0], "Inconsistent CPU timestamps %"PRIu64" and %"PRIu64".\n",
cpu_times[0], cpu_times[1]);
--
2.34.1
2
2
17 Jan '22
Psychonauts 2 creates an SRV on a swapchain image and lack of
VK_IMAGE_USAGE_SAMPLED_BIT results in failure to create a Vulkan
descriptor.
Signed-off-by: Conor McCarthy <cmccarthy(a)codeweavers.com>
---
dlls/dxgi/swapchain.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c
index 8d5f2f537..015a32498 100644
--- a/dlls/dxgi/swapchain.c
+++ b/dlls/dxgi/swapchain.c
@@ -1303,7 +1303,8 @@ static HRESULT d3d12_swapchain_create_user_buffers(struct d3d12_swapchain *swapc
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT
| VK_IMAGE_USAGE_TRANSFER_DST_BIT
- | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
+ | VK_IMAGE_USAGE_SAMPLED_BIT;
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
image_info.queueFamilyIndexCount = 0;
image_info.pQueueFamilyIndices = NULL;
@@ -1792,8 +1793,11 @@ static HRESULT d3d12_swapchain_create_vulkan_swapchain(struct d3d12_swapchain *s
usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
usage |= surface_caps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
usage |= surface_caps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ usage |= surface_caps.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT;
if (!(usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) || !(usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT))
WARN("Transfer not supported for swapchain images.\n");
+ if (!(usage & VK_IMAGE_USAGE_SAMPLED_BIT))
+ WARN("Sampling not supported for swapchain images.\n");
vk_swapchain_desc.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
vk_swapchain_desc.pNext = NULL;
--
2.34.1
3
2
17 Jan '22
From: Eric Pouech <eric.pouech(a)gmail.com>
v2: Initialize variable when declared.
Signed-off-by: Eric Pouech <eric.pouech(a)gmail.com>
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/msi/action.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index 9a47c2b068b..8ee9420af55 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -6973,7 +6973,7 @@ static UINT ITERATE_RemoveEnvironmentString( MSIRECORD *rec, LPVOID param )
LPCWSTR name, value, component;
WCHAR *p, *q, *deformatted = NULL, *new_value = NULL;
DWORD flags, type, size, len, len_value = 0, len_new_value;
- HKEY env;
+ HKEY env = NULL;
MSICOMPONENT *comp;
MSIRECORD *uirow;
int action = 0;
--
2.30.2
1
0
17 Jan '22
Signed-off-by: Alex Henrie <alexhenrie24(a)gmail.com>
---
dlls/ddraw/tests/ddraw1.c | 40 ++++++---------------------------------
1 file changed, 6 insertions(+), 34 deletions(-)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index efbecf04c2d..9d3bd542b70 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -941,15 +941,6 @@ static void test_coop_level_create_device_window(void)
device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
ok(!device_window, "Unexpected device window found.\n");
- /* Windows versions before 98 / NT5 don't support DDSCL_CREATEDEVICEWINDOW. */
- if (broken(hr == DDERR_INVALIDPARAMS))
- {
- win_skip("DDSCL_CREATEDEVICEWINDOW not supported, skipping test.\n");
- IDirectDraw_Release(ddraw);
- DestroyWindow(focus_window);
- return;
- }
-
hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr);
device_window = FindWindowA("DirectDrawDeviceWnd", "DirectDrawDeviceWnd");
@@ -1179,7 +1170,7 @@ static void test_clipper_blt(void)
}
hr = IDirectDrawSurface_BltFast(dst_surface, 0, 0, src_surface, NULL, DDBLTFAST_WAIT);
- ok(hr == DDERR_BLTFASTCANTCLIP || broken(hr == E_NOTIMPL /* NT4 */), "Got unexpected hr %#x.\n", hr);
+ ok(hr == DDERR_BLTFASTCANTCLIP, "Got unexpected hr %#x.\n", hr);
hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
ok(SUCCEEDED(hr), "Failed to set clipper window, hr %#x.\n", hr);
@@ -3152,13 +3143,6 @@ static void test_coop_level_mode_set(void)
hr = IDirectDrawSurface_Restore(primary);
ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
hr = set_display_mode(ddraw, param.ddraw_width, param.ddraw_height);
- if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
- {
- win_skip("Broken SetDisplayMode(), skipping remaining tests.\n");
- IDirectDrawSurface_Release(primary);
- IDirectDraw_Release(ddraw);
- goto done;
- }
ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
hr = IDirectDrawSurface_Restore(primary);
ok(hr == DDERR_WRONGMODE, "Got unexpected hr %#x.\n", hr);
@@ -3538,7 +3522,6 @@ static void test_coop_level_mode_set(void)
ref = IDirectDraw_Release(ddraw);
ok(ref == 0, "The ddraw object was not properly freed: refcount %u.\n", ref);
-done:
expect_messages = NULL;
DestroyWindow(window);
UnregisterClassA("ddraw_test_wndproc_wc", GetModuleHandleA(NULL));
@@ -3580,13 +3563,6 @@ static void test_coop_level_mode_set_multi(void)
/* With just a single ddraw object, the display mode is restored on
* release. */
hr = set_display_mode(ddraw1, 800, 600);
- if (hr == DDERR_NOEXCLUSIVEMODE /* NT4 testbot */)
- {
- win_skip("Broken SetDisplayMode(), skipping test.\n");
- IDirectDraw_Release(ddraw1);
- DestroyWindow(window);
- return;
- }
ok(SUCCEEDED(hr), "Failed to set display mode, hr %#x.\n", hr);
w = GetSystemMetrics(SM_CXSCREEN);
ok(w == 800, "Got unexpected screen width %u.\n", w);
@@ -3991,13 +3967,10 @@ static void test_initialize(void)
IDirectDraw_Release(ddraw);
CoUninitialize();
- if (0) /* This crashes on the W2KPROSP4 testbot. */
- {
- CoInitialize(NULL);
- hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirect3D, (void **)&d3d);
- ok(hr == E_NOINTERFACE, "CoCreateInstance returned hr %#x, expected E_NOINTERFACE.\n", hr);
- CoUninitialize();
- }
+ CoInitialize(NULL);
+ hr = CoCreateInstance(&CLSID_DirectDraw, NULL, CLSCTX_INPROC_SERVER, &IID_IDirect3D, (void **)&d3d);
+ todo_wine ok(hr == E_NOINTERFACE, "CoCreateInstance returned hr %#x, expected E_NOINTERFACE.\n", hr);
+ CoUninitialize();
}
static void test_coop_level_surf_create(void)
@@ -7691,8 +7664,7 @@ static void test_palette_alpha(void)
UINT retval;
hr = IDirectDrawSurface_GetDC(surface, &dc);
- ok(SUCCEEDED(hr) || broken(hr == DDERR_CANTCREATEDC) /* Win2k testbot */,
- "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
+ ok(SUCCEEDED(hr), "Failed to get DC, hr %#x, %s surface.\n", hr, test_data[i].name);
if (SUCCEEDED(hr))
{
retval = GetDIBColorTable(dc, 1, 1, &rgbquad);
--
2.34.1
2
6