Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- I don't know why I didn't think of this in the first place...
Makefile.am | 6 +++--- tests/{shader_runner_d3d12.c => shader_runner.c} | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename tests/{shader_runner_d3d12.c => shader_runner.c} (99%)
diff --git a/Makefile.am b/Makefile.am index db0a6f680..17fcae32f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -51,7 +51,7 @@ vkd3d_cross_tests = \ tests/hlsl_d3d12
vkd3d_shader_runners = \ - tests/shader_runner_d3d12 + tests/shader_runner
vkd3d_shader_tests = \ tests/abs.shader_test \ @@ -282,10 +282,10 @@ 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_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 \ diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner.c similarity index 99% rename from tests/shader_runner_d3d12.c rename to tests/shader_runner.c index 4a8d1f18e..5db963f51 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner.c @@ -643,7 +643,7 @@ static struct texture *get_texture(struct shader_context *context, unsigned int return NULL; }
-START_TEST(shader_runner_d3d12) +START_TEST(shader_runner) { static const struct test_context_desc desc = {
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- Makefile.am | 37 ++++++++++++++------ include/private/vkd3d_test.h | 19 +++++++---- tests/shader_runner.c | 49 +++++++------------------- tests/shader_runner.h | 37 ++++++++++++++++++++ tests/shader_runner_d3d12.c | 66 ++++++++++++++++++++++++++++++++++++ 5 files changed, 154 insertions(+), 54 deletions(-) create mode 100644 tests/shader_runner.h create mode 100644 tests/shader_runner_d3d12.c
diff --git a/Makefile.am b/Makefile.am index 17fcae32f..51fa6719e 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 - vkd3d_shader_tests = \ tests/abs.shader_test \ tests/cast-to-float.shader_test \ @@ -117,7 +114,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 \ @@ -277,12 +275,15 @@ 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_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 @@ -391,14 +392,17 @@ CROSS_CPPFLAGS = -I$(srcdir)/include -I$(srcdir)/include/private -I$(builddir)/i CROSS_CFLAGS = -g -O2 -Wall -municode ${CROSS_CPPFLAGS} -D__USE_MINGW_ANSI_STDIO=0 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@-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) @@ -414,6 +418,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 @@ -423,9 +433,8 @@ CROSS64_CC = @CROSSCC64@ CROSS64_DLLTOOL = @CROSSTARGET64@-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) @@ -441,6 +450,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 index 5db963f51..ef0b81d1b 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.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 @@ -43,6 +43,7 @@ */
#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, ...) @@ -115,16 +116,10 @@ struct texture unsigned int root_index; };
-enum shader_model -{ - SHADER_MODEL_4_0 = 0, - SHADER_MODEL_4_1, - SHADER_MODEL_5_0, - SHADER_MODEL_5_1, -}; - struct shader_context { + const struct shader_runner_ops *ops; + struct test_context c; enum shader_model minimum_shader_model;
@@ -140,22 +135,6 @@ struct shader_context size_t sampler_count; };
-static ID3D10Blob *compile_shader(const char *source, const char *target) -{ - ID3D10Blob *blob = NULL, *errors = NULL; - HRESULT hr; - - hr = D3DCompile(source, strlen(source), NULL, NULL, NULL, "main", target, 0, 0, &blob, &errors); - ok(hr == S_OK, "Failed to compile shader, hr %#x.\n", hr); - if (errors) - { - if (vkd3d_test_state.debug_level) - trace("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors)); - ID3D10Blob_Release(errors); - } - return blob; -} - static void free_texture(struct texture *texture) { ID3D12DescriptorHeap_Release(texture->heap); @@ -643,7 +622,7 @@ static struct texture *get_texture(struct shader_context *context, unsigned int return NULL; }
-START_TEST(shader_runner) +void run_shader_tests(int argc, char **argv, const struct shader_runner_ops *ops) { static const struct test_context_desc desc = { @@ -689,6 +668,7 @@ START_TEST(shader_runner) }
memset(&context, 0, sizeof(context)); + context.ops = ops; init_test_context(&context.c, &desc);
for (;;) @@ -709,20 +689,10 @@ START_TEST(shader_runner) break;
case STATE_SHADER_PIXEL: - { - static const char *const shader_models[] = - { - [SHADER_MODEL_4_0] = "ps_4_0", - [SHADER_MODEL_4_1] = "ps_4_1", - [SHADER_MODEL_5_0] = "ps_5_0", - [SHADER_MODEL_5_1] = "ps_5_1", - }; - - if (!(context.ps_code = compile_shader(shader_source, shader_models[context.minimum_shader_model]))) + if (!(context.ps_code = context.ops->compile_shader(shader_source, context.minimum_shader_model))) return; shader_source_len = 0; break; - }
case STATE_SHADER_INVALID_PIXEL: { @@ -926,3 +896,8 @@ START_TEST(shader_runner)
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..b00803cff --- /dev/null +++ b/tests/shader_runner.h @@ -0,0 +1,37 @@ +/* + * 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" + +enum shader_model +{ + SHADER_MODEL_4_0 = 0, + SHADER_MODEL_4_1, + SHADER_MODEL_5_0, + SHADER_MODEL_5_1, +}; + +struct shader_runner_ops +{ + ID3D10Blob *(*compile_shader)(const char *source, enum shader_model minimum_shader_model); +}; + +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 new file mode 100644 index 000000000..6343f78e9 --- /dev/null +++ b/tests/shader_runner_d3d12.c @@ -0,0 +1,66 @@ +/* + * 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 + */ + +#ifdef __MINGW32__ +# define _HRESULT_DEFINED +typedef int HRESULT; +#endif + +#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" + +static ID3D10Blob *d3d12_runner_compile_shader(const char *source, enum shader_model shader_model) +{ + ID3D10Blob *blob = NULL, *errors = NULL; + HRESULT hr; + + static const char *const shader_models[] = + { + [SHADER_MODEL_4_0] = "ps_4_0", + [SHADER_MODEL_4_1] = "ps_4_1", + [SHADER_MODEL_5_0] = "ps_5_0", + [SHADER_MODEL_5_1] = "ps_5_1", + }; + + hr = D3DCompile(source, strlen(source), NULL, NULL, NULL, "main", + shader_models[shader_model], 0, 0, &blob, &errors); + ok(hr == S_OK, "Failed to compile shader, hr %#x.\n", hr); + if (errors) + { + if (vkd3d_test_state.debug_level) + trace("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors)); + ID3D10Blob_Release(errors); + } + return blob; +} + +static const struct shader_runner_ops d3d12_runner_ops = +{ + .compile_shader = d3d12_runner_compile_shader, +}; + +void run_shader_tests_d3d12(int argc, char **argv) +{ + run_shader_tests(argc, argv, &d3d12_runner_ops); +}
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- Makefile.am | 3 +- tests/d3d12_test_utils.h | 5 +- tests/shader_runner.c | 285 ++++++------------------------------ tests/shader_runner.h | 58 +++++++- tests/shader_runner_d3d12.c | 200 +++++++++++++++++++++++-- tests/utils.h | 58 ++++++++ 6 files changed, 351 insertions(+), 258 deletions(-) create mode 100644 tests/utils.h
diff --git a/Makefile.am b/Makefile.am index 51fa6719e..5d996560f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -115,7 +115,8 @@ vkd3d_shader_tests = \ vkd3d_test_headers = \ tests/d3d12_crosstest.h \ tests/d3d12_test_utils.h \ - tests/shader_runner.h + tests/shader_runner.h \ + tests/utils.h
vkd3d_demos = \ demos/vkd3d-gears \ diff --git a/tests/d3d12_test_utils.h b/tests/d3d12_test_utils.h index b8227282e..bab0c9ce2 100644 --- a/tests/d3d12_test_utils.h +++ b/tests/d3d12_test_utils.h @@ -19,10 +19,7 @@ #ifndef __VKD3D_D3D12_TEST_UTILS_H #define __VKD3D_D3D12_TEST_UTILS_H
-struct vec4 -{ - float x, y, z, w; -}; +#include "utils.h"
#define wait_queue_idle(a, b) wait_queue_idle_(__LINE__, a, b) static void wait_queue_idle_(unsigned int line, ID3D12Device *device, ID3D12CommandQueue *queue); diff --git a/tests/shader_runner.c b/tests/shader_runner.c index ef0b81d1b..74b70890f 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -42,9 +42,24 @@ * DEALINGS IN THE SOFTWARE. */
-#include "d3d12_crosstest.h" -#include "shader_runner.h" +#ifdef __MINGW32__ +# define _HRESULT_DEFINED +typedef int HRESULT; +#endif + +#define COBJMACROS +#define CONST_VTABLE +#include "config.h" +#include <ctype.h> #include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include "vkd3d_windows.h" +#include "vkd3d_d3dcommon.h" +#include "vkd3d_d3dcompiler.h" +#include "vkd3d_common.h" +#include "vkd3d_test.h" +#include "shader_runner.h"
static void VKD3D_NORETURN VKD3D_PRINTF_FUNC(1, 2) fatal_error(const char *format, ...) { @@ -56,89 +71,8 @@ static void VKD3D_NORETURN VKD3D_PRINTF_FUNC(1, 2) fatal_error(const char *forma 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; - enum shader_model minimum_shader_model; - - 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)); } @@ -352,119 +286,11 @@ static void parse_test_directive(struct shader_context *context, const char *lin { 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); + context->ops->draw_quad(context); } else if (match_string(line, "probe all rgba", &line)) { + static const RECT rect = {0, 0, 640, 480}; unsigned int ulps; struct vec4 v; int ret; @@ -474,13 +300,12 @@ static void parse_test_directive(struct shader_context *context, const char *lin 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); + + context->ops->probe_vec4(context, &rect, &v, ulps); } 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; @@ -492,18 +317,14 @@ static void parse_test_directive(struct shader_context *context, const char *lin 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); + context->ops->probe_vec4(context, &rect, &v, ulps); } else if (match_string(line, "probe rgba", &line)) { - struct resource_readback rb; unsigned int x, y, ulps; struct vec4 v; RECT rect; @@ -515,14 +336,11 @@ static void parse_test_directive(struct shader_context *context, const char *lin 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); + context->ops->probe_vec4(context, &rect, &v, ulps); } else if (match_string(line, "uniform", &line)) { @@ -622,30 +440,18 @@ static struct texture *get_texture(struct shader_context *context, unsigned int return NULL; }
-void run_shader_tests(int argc, char **argv, const struct shader_runner_ops *ops) +void run_shader_tests(struct shader_context *context, 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] != '-') @@ -667,9 +473,8 @@ void run_shader_tests(int argc, char **argv, const struct shader_runner_ops *ops return; }
- memset(&context, 0, sizeof(context)); - context.ops = ops; - init_test_context(&context.c, &desc); + memset(context, 0, sizeof(*context)); + context->ops = ops;
for (;;) { @@ -689,7 +494,8 @@ void run_shader_tests(int argc, char **argv, const struct shader_runner_ops *ops break;
case STATE_SHADER_PIXEL: - if (!(context.ps_code = context.ops->compile_shader(shader_source, context.minimum_shader_model))) + if (!(context->ps_code = context->ops->compile_shader(context, + shader_source, context->minimum_shader_model))) return; shader_source_len = 0; break; @@ -784,9 +590,9 @@ void run_shader_tests(int argc, char **argv, const struct shader_runner_ops *ops { state = STATE_SHADER_PIXEL;
- if (context.ps_code) - ID3D10Blob_Release(context.ps_code); - context.ps_code = NULL; + if (context->ps_code) + ID3D10Blob_Release(context->ps_code); + context->ps_code = NULL; } else if (!strcmp(line, "[pixel shader fail]\n")) { @@ -796,15 +602,15 @@ void run_shader_tests(int argc, char **argv, const struct shader_runner_ops *ops { state = STATE_SAMPLER;
- if ((current_sampler = get_sampler(&context, index))) + 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]; + 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; @@ -817,15 +623,15 @@ void run_shader_tests(int argc, char **argv, const struct shader_runner_ops *ops { state = STATE_TEXTURE;
- if ((current_texture = get_texture(&context, index))) + 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]; + 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; @@ -870,7 +676,7 @@ void run_shader_tests(int argc, char **argv, const struct shader_runner_ops *ops }
case STATE_REQUIRE: - parse_require_directive(&context, line); + parse_require_directive(context, line); break;
case STATE_SAMPLER: @@ -882,17 +688,16 @@ void run_shader_tests(int argc, char **argv, const struct shader_runner_ops *ops break;
case STATE_TEST: - parse_test_directive(&context, line); + 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); + if (context->ps_code) + ID3D10Blob_Release(context->ps_code); + for (i = 0; i < context->texture_count; ++i) + free_texture(&context->textures[i]);
fclose(f); } diff --git a/tests/shader_runner.h b/tests/shader_runner.h index b00803cff..e9001eeda 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -18,6 +18,9 @@
#include "vkd3d_windows.h" #include "vkd3d_d3dcommon.h" +#include "vkd3d_d3d12.h" +#include "vkd3d_dxgiformat.h" +#include "utils.h"
enum shader_model { @@ -27,11 +30,62 @@ enum shader_model SHADER_MODEL_5_1, };
+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; + + ID3D10Blob *ps_code; + enum shader_model minimum_shader_model; + + uint32_t *uniforms; + size_t uniform_count; + + struct texture *textures; + size_t texture_count; + + struct sampler *samplers; + size_t sampler_count; +}; + struct shader_runner_ops { - ID3D10Blob *(*compile_shader)(const char *source, enum shader_model minimum_shader_model); + ID3D10Blob *(*compile_shader)(struct shader_context *context, const char *source, enum shader_model minimum_shader_model); + void (*draw_quad)(struct shader_context *context); + void (*probe_vec4)(struct shader_context *context, const RECT *rect, const struct vec4 *v, unsigned int ulps); };
-void run_shader_tests(int argc, char **argv, const struct shader_runner_ops *ops); +void run_shader_tests(struct shader_context *context, 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 6343f78e9..bb0288e83 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -16,21 +16,28 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#ifdef __MINGW32__ -# define _HRESULT_DEFINED -typedef int HRESULT; -#endif - +#include "config.h" +#include <assert.h> #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 "d3d12_crosstest.h" #include "shader_runner.h"
-static ID3D10Blob *d3d12_runner_compile_shader(const char *source, enum shader_model shader_model) +struct d3d12_shader_context +{ + struct shader_context c; + + struct test_context test_context; +}; + +static struct d3d12_shader_context *d3d12_shader_context(struct shader_context *c) +{ + return CONTAINING_RECORD(c, struct d3d12_shader_context, c); +} + +static ID3D10Blob *d3d12_runner_compile_shader(struct shader_context *c, + const char *source, enum shader_model shader_model) { ID3D10Blob *blob = NULL, *errors = NULL; HRESULT hr; @@ -55,12 +62,183 @@ static ID3D10Blob *d3d12_runner_compile_shader(const char *source, enum shader_m return blob; }
+static void d3d12_runner_draw_quad(struct shader_context *c) +{ + struct d3d12_shader_context *context = d3d12_shader_context(c); + struct test_context *test_context = &context->test_context; + + D3D12_SHADER_BYTECODE ps + = {ID3D10Blob_GetBufferPointer(context->c.ps_code), ID3D10Blob_GetBufferSize(context->c.ps_code)}; + ID3D12GraphicsCommandList *command_list = test_context->list; + D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {0}; + D3D12_ROOT_PARAMETER root_params[3], *root_param; + ID3D12CommandQueue *queue = test_context->queue; + D3D12_STATIC_SAMPLER_DESC static_samplers[1]; + ID3D12Device *device = test_context->device; + 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->c.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->c.uniform_count; + root_param->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + } + + for (i = 0; i < context->c.texture_count; ++i) + { + struct texture *texture = &context->c.textures[i]; + D3D12_SUBRESOURCE_DATA resource_data; + D3D12_DESCRIPTOR_RANGE *range; + ID3D12Resource *resource; + + range = &texture->descriptor_range; + + 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; + + texture->heap = create_gpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1); + resource = create_default_texture(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(resource, &resource_data, 1, queue, command_list); + reset_command_list(command_list, test_context->allocator); + transition_resource_state(command_list, resource, D3D12_RESOURCE_STATE_COPY_DEST, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + ID3D12Device_CreateShaderResourceView(device, resource, + NULL, get_cpu_descriptor_handle(test_context, texture->heap, 0)); + + texture->resource = resource; + } + + assert(root_signature_desc.NumParameters <= ARRAY_SIZE(root_params)); + + for (i = 0; i < context->c.sampler_count; ++i) + { + D3D12_STATIC_SAMPLER_DESC *sampler_desc = &static_samplers[root_signature_desc.NumStaticSamplers++]; + const struct sampler *sampler = &context->c.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 (test_context->root_signature) + ID3D12RootSignature_Release(test_context->root_signature); + hr = create_root_signature(device, &root_signature_desc, &test_context->root_signature); + ok(hr == S_OK, "Failed to create root signature, hr %#x.\n", hr); + + pso = create_pipeline_state(device, test_context->root_signature, + test_context->render_target_desc.Format, NULL, &ps, NULL); + if (!pso) + return; + vkd3d_array_reserve((void **)&test_context->pso, &test_context->pso_capacity, + test_context->pso_count + 1, sizeof(*test_context->pso)); + test_context->pso[test_context->pso_count++] = pso; + + ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, test_context->root_signature); + if (context->c.uniform_count) + ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(command_list, uniform_index, + context->c.uniform_count, context->c.uniforms, 0); + for (i = 0; i < context->c.texture_count; ++i) + { + struct texture *texture = &context->c.textures[i]; + + ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, texture->root_index, + get_gpu_descriptor_handle(test_context, texture->heap, 0)); + } + + ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &test_context->rtv, false, NULL); + ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &test_context->scissor_rect); + ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &test_context->viewport); + ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, test_context->rtv, clear_color, 0, NULL); + ID3D12GraphicsCommandList_SetPipelineState(command_list, pso); + ID3D12GraphicsCommandList_DrawInstanced(command_list, 3, 1, 0, 0); + transition_resource_state(command_list, test_context->render_target, + D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); + + /* Finish the command list so that we can destroy objects. */ + hr = ID3D12GraphicsCommandList_Close(command_list); + ok(hr == S_OK, "Failed to close command list, hr %#x.\n", hr); + exec_command_list(queue, command_list); + wait_queue_idle(device, queue); + reset_command_list(command_list, test_context->allocator); + + for (i = 0; i < context->c.texture_count; ++i) + { + struct texture *texture = &context->c.textures[i]; + + ID3D12DescriptorHeap_Release(texture->heap); + ID3D12Resource_Release(texture->resource); + free(texture); + } +} + +static void d3d12_runner_probe_vec4(struct shader_context *c, + const RECT *rect, const struct vec4 *v, unsigned int ulps) +{ + struct d3d12_shader_context *context = d3d12_shader_context(c); + struct test_context *test_context = &context->test_context; + struct resource_readback rb; + + get_texture_readback_with_command_list(test_context->render_target, 0, &rb, + test_context->queue, test_context->list); + check_readback_data_vec4(&rb, rect, v, ulps); + release_resource_readback(&rb); + reset_command_list(test_context->list, test_context->allocator); +} + static const struct shader_runner_ops d3d12_runner_ops = { .compile_shader = d3d12_runner_compile_shader, + .draw_quad = d3d12_runner_draw_quad, + .probe_vec4 = d3d12_runner_probe_vec4, };
void run_shader_tests_d3d12(int argc, char **argv) { - run_shader_tests(argc, argv, &d3d12_runner_ops); + static const struct test_context_desc desc = + { + .rt_width = 640, + .rt_height = 480, + .no_root_signature = true, + .rt_format = DXGI_FORMAT_R32G32B32A32_FLOAT, + }; + struct d3d12_shader_context context; + + parse_args(argc, argv); + enable_d3d12_debug_layer(argc, argv); + init_adapter_info(); + init_test_context(&context.test_context, &desc); + run_shader_tests(&context.c, argc, argv, &d3d12_runner_ops); + destroy_test_context(&context.test_context); } diff --git a/tests/utils.h b/tests/utils.h new file mode 100644 index 000000000..825520c27 --- /dev/null +++ b/tests/utils.h @@ -0,0 +1,58 @@ +/* + * Copyright 2016-2018 Józef Kucia 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 + */ + +#ifndef __VKD3D_TEST_UTILS_H +#define __VKD3D_TEST_UTILS_H + +#include <stdbool.h> +#include <stdlib.h> + +struct vec4 +{ + float x, y, z, w; +}; + +static inline 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; +} + +#endif
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- tests/shader_runner.c | 60 ++++++++++++++++------------------ tests/shader_runner.h | 11 +++++-- tests/shader_runner_d3d12.c | 65 ++++++++++++++++++++++--------------- 3 files changed, 75 insertions(+), 61 deletions(-)
diff --git a/tests/shader_runner.c b/tests/shader_runner.c index 74b70890f..aabae5ae0 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -71,12 +71,6 @@ static void VKD3D_NORETURN VKD3D_PRINTF_FUNC(1, 2) fatal_error(const char *forma exit(1); }
-static void free_texture(struct texture *texture) -{ - free(texture->data); - memset(texture, 0, sizeof(*texture)); -} - enum parse_state { STATE_NONE, @@ -135,7 +129,7 @@ static void parse_require_directive(struct shader_context *context, const char * } }
-static void parse_texture_format(struct texture *texture, const char *line) +static void parse_texture_format(struct texture_params *texture, const char *line) { static const struct { @@ -228,7 +222,7 @@ static void parse_sampler_directive(struct sampler *sampler, const char *line) } }
-static void parse_texture_directive(struct texture *texture, const char *line) +static void parse_texture_directive(struct texture_params *texture, const char *line) { int ret;
@@ -425,26 +419,29 @@ static struct sampler *get_sampler(struct shader_context *context, unsigned int return NULL; }
-static struct texture *get_texture(struct shader_context *context, unsigned int slot) +static void set_texture(struct shader_context *context, struct texture *texture) { - struct texture *texture; size_t i;
for (i = 0; i < context->texture_count; ++i) { - texture = &context->textures[i]; - if (texture->slot == slot) - return texture; + if (context->textures[i]->slot == texture->slot) + { + context->ops->destroy_texture(context, context->textures[i]); + context->textures[i] = texture; + return; + } }
- return NULL; + context->textures = realloc(context->textures, (context->texture_count + 1) * sizeof(*context->textures)); + context->textures[context->texture_count++] = texture; }
void run_shader_tests(struct shader_context *context, int argc, char **argv, const struct shader_runner_ops *ops) { size_t shader_source_size = 0, shader_source_len = 0; struct sampler *current_sampler = NULL; - struct texture *current_texture = NULL; + struct texture_params current_texture; enum parse_state state = STATE_NONE; unsigned int i, line_number = 0; const char *filename = NULL; @@ -490,7 +487,11 @@ void run_shader_tests(struct shader_context *context, int argc, char **argv, con case STATE_REQUIRE: case STATE_SAMPLER: case STATE_TEST: + break; + case STATE_TEXTURE: + set_texture(context, context->ops->create_texture(context, ¤t_texture)); + free(current_texture.data); break;
case STATE_SHADER_PIXEL: @@ -623,21 +624,12 @@ void run_shader_tests(struct shader_context *context, int argc, char **argv, con { 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; + memset(¤t_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")) { @@ -684,7 +676,7 @@ void run_shader_tests(struct shader_context *context, int argc, char **argv, con break;
case STATE_TEXTURE: - parse_texture_directive(current_texture, line); + parse_texture_directive(¤t_texture, line); break;
case STATE_TEST: @@ -697,7 +689,11 @@ void run_shader_tests(struct shader_context *context, int argc, char **argv, con if (context->ps_code) ID3D10Blob_Release(context->ps_code); for (i = 0; i < context->texture_count; ++i) - free_texture(&context->textures[i]); + { + if (context->textures[i]) + context->ops->destroy_texture(context, context->textures[i]); + } + free(context->textures);
fclose(f); } diff --git a/tests/shader_runner.h b/tests/shader_runner.h index e9001eeda..c541b56e8 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -45,7 +45,7 @@ struct sampler D3D12_TEXTURE_ADDRESS_MODE u_address, v_address, w_address; };
-struct texture +struct texture_params { unsigned int slot;
@@ -55,6 +55,11 @@ struct texture unsigned int width, height; uint8_t *data; size_t data_size, data_capacity; +}; + +struct texture +{ + unsigned int slot;
D3D12_DESCRIPTOR_RANGE descriptor_range; ID3D12DescriptorHeap *heap; @@ -72,7 +77,7 @@ struct shader_context uint32_t *uniforms; size_t uniform_count;
- struct texture *textures; + struct texture **textures; size_t texture_count;
struct sampler *samplers; @@ -82,6 +87,8 @@ struct shader_context struct shader_runner_ops { ID3D10Blob *(*compile_shader)(struct shader_context *context, const char *source, enum shader_model minimum_shader_model); + struct texture *(*create_texture)(struct shader_context *context, const struct texture_params *params); + void (*destroy_texture)(struct shader_context *context, struct texture *texture); void (*draw_quad)(struct shader_context *context); void (*probe_vec4)(struct shader_context *context, const RECT *rect, const struct vec4 *v, unsigned int ulps); }; diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index bb0288e83..94399aea6 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -62,6 +62,40 @@ static ID3D10Blob *d3d12_runner_compile_shader(struct shader_context *c, return blob; }
+static struct texture *d3d12_runner_create_texture(struct shader_context *c, const struct texture_params *params) +{ + struct d3d12_shader_context *context = d3d12_shader_context(c); + struct test_context *test_context = &context->test_context; + ID3D12Device *device = test_context->device; + D3D12_SUBRESOURCE_DATA resource_data; + struct texture *texture; + + texture = calloc(1, sizeof(*texture)); + + texture->slot = params->slot; + + texture->heap = create_gpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1); + texture->resource = create_default_texture(device, params->width, params->height, + params->format, 0, D3D12_RESOURCE_STATE_COPY_DEST); + resource_data.pData = params->data; + resource_data.SlicePitch = resource_data.RowPitch = params->width * params->texel_size; + upload_texture_data(texture->resource, &resource_data, 1, test_context->queue, test_context->list); + reset_command_list(test_context->list, test_context->allocator); + transition_resource_state(test_context->list, texture->resource, D3D12_RESOURCE_STATE_COPY_DEST, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + ID3D12Device_CreateShaderResourceView(device, texture->resource, + NULL, get_cpu_descriptor_handle(test_context, texture->heap, 0)); + + return texture; +} + +static void d3d12_runner_destroy_texture(struct shader_context *c, struct texture *texture) +{ + ID3D12DescriptorHeap_Release(texture->heap); + ID3D12Resource_Release(texture->resource); + free(texture); +} + static void d3d12_runner_draw_quad(struct shader_context *c) { struct d3d12_shader_context *context = d3d12_shader_context(c); @@ -99,10 +133,8 @@ static void d3d12_runner_draw_quad(struct shader_context *c)
for (i = 0; i < context->c.texture_count; ++i) { - struct texture *texture = &context->c.textures[i]; - D3D12_SUBRESOURCE_DATA resource_data; + struct texture *texture = context->c.textures[i]; D3D12_DESCRIPTOR_RANGE *range; - ID3D12Resource *resource;
range = &texture->descriptor_range;
@@ -118,20 +150,6 @@ static void d3d12_runner_draw_quad(struct shader_context *c) range->BaseShaderRegister = texture->slot; range->RegisterSpace = 0; range->OffsetInDescriptorsFromTableStart = 0; - - texture->heap = create_gpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1); - resource = create_default_texture(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(resource, &resource_data, 1, queue, command_list); - reset_command_list(command_list, test_context->allocator); - transition_resource_state(command_list, resource, D3D12_RESOURCE_STATE_COPY_DEST, - D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - ID3D12Device_CreateShaderResourceView(device, resource, - NULL, get_cpu_descriptor_handle(test_context, texture->heap, 0)); - - texture->resource = resource; }
assert(root_signature_desc.NumParameters <= ARRAY_SIZE(root_params)); @@ -170,7 +188,7 @@ static void d3d12_runner_draw_quad(struct shader_context *c) context->c.uniform_count, context->c.uniforms, 0); for (i = 0; i < context->c.texture_count; ++i) { - struct texture *texture = &context->c.textures[i]; + struct texture *texture = context->c.textures[i];
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, texture->root_index, get_gpu_descriptor_handle(test_context, texture->heap, 0)); @@ -192,15 +210,6 @@ static void d3d12_runner_draw_quad(struct shader_context *c) exec_command_list(queue, command_list); wait_queue_idle(device, queue); reset_command_list(command_list, test_context->allocator); - - for (i = 0; i < context->c.texture_count; ++i) - { - struct texture *texture = &context->c.textures[i]; - - ID3D12DescriptorHeap_Release(texture->heap); - ID3D12Resource_Release(texture->resource); - free(texture); - } }
static void d3d12_runner_probe_vec4(struct shader_context *c, @@ -220,6 +229,8 @@ static void d3d12_runner_probe_vec4(struct shader_context *c, static const struct shader_runner_ops d3d12_runner_ops = { .compile_shader = d3d12_runner_compile_shader, + .create_texture = d3d12_runner_create_texture, + .destroy_texture = d3d12_runner_destroy_texture, .draw_quad = d3d12_runner_draw_quad, .probe_vec4 = d3d12_runner_probe_vec4, };
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- tests/shader_runner.h | 5 ----- tests/shader_runner_d3d12.c | 31 ++++++++++++++++++++++++------- 2 files changed, 24 insertions(+), 12 deletions(-)
diff --git a/tests/shader_runner.h b/tests/shader_runner.h index c541b56e8..2e6d3606f 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -60,11 +60,6 @@ struct texture_params struct texture { unsigned int slot; - - D3D12_DESCRIPTOR_RANGE descriptor_range; - ID3D12DescriptorHeap *heap; - ID3D12Resource *resource; - unsigned int root_index; };
struct shader_context diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index 94399aea6..f79c53be4 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -24,6 +24,21 @@ #include "d3d12_crosstest.h" #include "shader_runner.h"
+struct d3d12_texture +{ + struct texture t; + + D3D12_DESCRIPTOR_RANGE descriptor_range; + ID3D12DescriptorHeap *heap; + ID3D12Resource *resource; + unsigned int root_index; +}; + +static struct d3d12_texture *d3d12_texture(struct texture *t) +{ + return CONTAINING_RECORD(t, struct d3d12_texture, t); +} + struct d3d12_shader_context { struct shader_context c; @@ -68,11 +83,11 @@ static struct texture *d3d12_runner_create_texture(struct shader_context *c, con struct test_context *test_context = &context->test_context; ID3D12Device *device = test_context->device; D3D12_SUBRESOURCE_DATA resource_data; - struct texture *texture; + struct d3d12_texture *texture;
texture = calloc(1, sizeof(*texture));
- texture->slot = params->slot; + texture->t.slot = params->slot;
texture->heap = create_gpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 1); texture->resource = create_default_texture(device, params->width, params->height, @@ -86,11 +101,13 @@ static struct texture *d3d12_runner_create_texture(struct shader_context *c, con ID3D12Device_CreateShaderResourceView(device, texture->resource, NULL, get_cpu_descriptor_handle(test_context, texture->heap, 0));
- return texture; + return &texture->t; }
-static void d3d12_runner_destroy_texture(struct shader_context *c, struct texture *texture) +static void d3d12_runner_destroy_texture(struct shader_context *c, struct texture *t) { + struct d3d12_texture *texture = d3d12_texture(t); + ID3D12DescriptorHeap_Release(texture->heap); ID3D12Resource_Release(texture->resource); free(texture); @@ -133,7 +150,7 @@ static void d3d12_runner_draw_quad(struct shader_context *c)
for (i = 0; i < context->c.texture_count; ++i) { - struct texture *texture = context->c.textures[i]; + struct d3d12_texture *texture = d3d12_texture(context->c.textures[i]); D3D12_DESCRIPTOR_RANGE *range;
range = &texture->descriptor_range; @@ -147,7 +164,7 @@ static void d3d12_runner_draw_quad(struct shader_context *c)
range->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; range->NumDescriptors = 1; - range->BaseShaderRegister = texture->slot; + range->BaseShaderRegister = texture->t.slot; range->RegisterSpace = 0; range->OffsetInDescriptorsFromTableStart = 0; } @@ -188,7 +205,7 @@ static void d3d12_runner_draw_quad(struct shader_context *c) context->c.uniform_count, context->c.uniforms, 0); for (i = 0; i < context->c.texture_count; ++i) { - struct texture *texture = context->c.textures[i]; + struct d3d12_texture *texture = d3d12_texture(context->c.textures[i]);
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, texture->root_index, get_gpu_descriptor_handle(test_context, texture->heap, 0));
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- tests/shader_runner.c | 14 +++++--------- tests/shader_runner.h | 3 +-- tests/shader_runner_d3d12.c | 14 +++++++++----- 3 files changed, 15 insertions(+), 16 deletions(-)
diff --git a/tests/shader_runner.c b/tests/shader_runner.c index aabae5ae0..12fdad308 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -495,10 +495,11 @@ void run_shader_tests(struct shader_context *context, int argc, char **argv, con break;
case STATE_SHADER_PIXEL: - if (!(context->ps_code = context->ops->compile_shader(context, - shader_source, context->minimum_shader_model))) - return; + free(context->ps_source); + context->ps_source = shader_source; + shader_source = NULL; shader_source_len = 0; + shader_source_size = 0; break;
case STATE_SHADER_INVALID_PIXEL: @@ -590,10 +591,6 @@ void run_shader_tests(struct shader_context *context, int argc, char **argv, con else 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")) { @@ -686,8 +683,7 @@ void run_shader_tests(struct shader_context *context, int argc, char **argv, con } }
- if (context->ps_code) - ID3D10Blob_Release(context->ps_code); + free(context->ps_source); for (i = 0; i < context->texture_count; ++i) { if (context->textures[i]) diff --git a/tests/shader_runner.h b/tests/shader_runner.h index 2e6d3606f..6865d4d05 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -66,7 +66,7 @@ struct shader_context { const struct shader_runner_ops *ops;
- ID3D10Blob *ps_code; + char *ps_source; enum shader_model minimum_shader_model;
uint32_t *uniforms; @@ -81,7 +81,6 @@ struct shader_context
struct shader_runner_ops { - ID3D10Blob *(*compile_shader)(struct shader_context *context, const char *source, enum shader_model minimum_shader_model); struct texture *(*create_texture)(struct shader_context *context, const struct texture_params *params); void (*destroy_texture)(struct shader_context *context, struct texture *texture); void (*draw_quad)(struct shader_context *context); diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index f79c53be4..3b415ec76 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -51,8 +51,7 @@ static struct d3d12_shader_context *d3d12_shader_context(struct shader_context * return CONTAINING_RECORD(c, struct d3d12_shader_context, c); }
-static ID3D10Blob *d3d12_runner_compile_shader(struct shader_context *c, - const char *source, enum shader_model shader_model) +static ID3D10Blob *compile_shader(const char *source, enum shader_model shader_model) { ID3D10Blob *blob = NULL, *errors = NULL; HRESULT hr; @@ -118,8 +117,6 @@ static void d3d12_runner_draw_quad(struct shader_context *c) struct d3d12_shader_context *context = d3d12_shader_context(c); struct test_context *test_context = &context->test_context;
- D3D12_SHADER_BYTECODE ps - = {ID3D10Blob_GetBufferPointer(context->c.ps_code), ID3D10Blob_GetBufferSize(context->c.ps_code)}; ID3D12GraphicsCommandList *command_list = test_context->list; D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {0}; D3D12_ROOT_PARAMETER root_params[3], *root_param; @@ -128,10 +125,15 @@ static void d3d12_runner_draw_quad(struct shader_context *c) ID3D12Device *device = test_context->device; static const float clear_color[4]; unsigned int uniform_index; + D3D12_SHADER_BYTECODE ps; ID3D12PipelineState *pso; + ID3D10Blob *ps_code; HRESULT hr; size_t i;
+ if (!(ps_code = compile_shader(context->c.ps_source, context->c.minimum_shader_model))) + return; + root_signature_desc.NumParameters = 0; root_signature_desc.pParameters = root_params; root_signature_desc.NumStaticSamplers = 0; @@ -191,8 +193,11 @@ static void d3d12_runner_draw_quad(struct shader_context *c) hr = create_root_signature(device, &root_signature_desc, &test_context->root_signature); ok(hr == S_OK, "Failed to create root signature, hr %#x.\n", hr);
+ ps.pShaderBytecode = ID3D10Blob_GetBufferPointer(ps_code); + ps.BytecodeLength = ID3D10Blob_GetBufferSize(ps_code); pso = create_pipeline_state(device, test_context->root_signature, test_context->render_target_desc.Format, NULL, &ps, NULL); + ID3D10Blob_Release(ps_code); if (!pso) return; vkd3d_array_reserve((void **)&test_context->pso, &test_context->pso_capacity, @@ -245,7 +250,6 @@ static void d3d12_runner_probe_vec4(struct shader_context *c,
static const struct shader_runner_ops d3d12_runner_ops = { - .compile_shader = d3d12_runner_compile_shader, .create_texture = d3d12_runner_create_texture, .destroy_texture = d3d12_runner_destroy_texture, .draw_quad = d3d12_runner_draw_quad,
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- tests/shader_runner.c | 36 ++++++++++++------------------------ tests/shader_runner.h | 2 +- 2 files changed, 13 insertions(+), 25 deletions(-)
diff --git a/tests/shader_runner.c b/tests/shader_runner.c index 12fdad308..ae5daa70b 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -276,6 +276,14 @@ static void parse_texture_directive(struct texture_params *texture, const char * } }
+static void set_uniforms(struct shader_context *context, size_t offset, size_t count, const void *uniforms) +{ + context->uniform_count = max(context->uniform_count, offset + count); + vkd3d_array_reserve((void **)&context->uniforms, &context->uniform_capacity, + context->uniform_count, sizeof(*context->uniforms)); + memcpy(context->uniforms + offset, uniforms, count * sizeof(*context->uniforms)); +} + static void parse_test_directive(struct shader_context *context, const char *line) { if (match_string(line, "draw quad", &line)) @@ -350,12 +358,7 @@ static void parse_test_directive(struct shader_context *context, const char *lin
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)); + set_uniforms(context, offset, 4, &v); } else if (match_string(line, "float", &line)) { @@ -363,12 +366,7 @@ static void parse_test_directive(struct shader_context *context, const char *lin
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)); + set_uniforms(context, offset, 1, &f); } else if (match_string(line, "int", &line)) { @@ -376,12 +374,7 @@ static void parse_test_directive(struct shader_context *context, const char *lin
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)); + set_uniforms(context, offset, 1, &i); } else if (match_string(line, "uint", &line)) { @@ -389,12 +382,7 @@ static void parse_test_directive(struct shader_context *context, const char *lin
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)); + set_uniforms(context, offset, 1, &u); } } else diff --git a/tests/shader_runner.h b/tests/shader_runner.h index 6865d4d05..9a687edbc 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -70,7 +70,7 @@ struct shader_context enum shader_model minimum_shader_model;
uint32_t *uniforms; - size_t uniform_count; + size_t uniform_count, uniform_capacity;
struct texture **textures; size_t texture_count;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- Makefile.am | 1 + tests/d3d12.c | 5 - tests/d3d12_test_utils.h | 33 -- tests/shader_runner.c | 7 +- tests/shader_runner.h | 4 + tests/shader_runner_d3d11.c | 639 ++++++++++++++++++++++++++++++++++++ tests/utils.h | 39 +++ 7 files changed, 689 insertions(+), 39 deletions(-) create mode 100644 tests/shader_runner_d3d11.c
diff --git a/Makefile.am b/Makefile.am index 5d996560f..82807a428 100644 --- a/Makefile.am +++ b/Makefile.am @@ -395,6 +395,7 @@ EXTRA_DIST += $(cross_implibs:=.cross32.def) $(cross_implibs:=.cross64.def)
shader_runner_cross_sources = \ $(srcdir)/tests/shader_runner.c \ + $(srcdir)/tests/shader_runner_d3d11.c \ $(srcdir)/tests/shader_runner_d3d12.c
if HAVE_CROSSTARGET32 diff --git a/tests/d3d12.c b/tests/d3d12.c index 82f353a72..eb6217bc9 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -26,11 +26,6 @@ static PFN_D3D12_CREATE_VERSIONED_ROOT_SIGNATURE_DESERIALIZER pfn_D3D12CreateVersionedRootSignatureDeserializer; static PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE pfn_D3D12SerializeVersionedRootSignature;
-struct vec2 -{ - float x, y; -}; - struct uvec4 { unsigned int x, y, z, w; diff --git a/tests/d3d12_test_utils.h b/tests/d3d12_test_utils.h index bab0c9ce2..7186a73e7 100644 --- a/tests/d3d12_test_utils.h +++ b/tests/d3d12_test_utils.h @@ -82,31 +82,6 @@ static void set_viewport(D3D12_VIEWPORT *vp, float x, float y, vp->MaxDepth = max_depth; }
-static bool compare_float(float f, float g, unsigned int ulps) -{ - int x, y; - union - { - float f; - int i; - } u; - - u.f = f; - x = u.i; - u.f = g; - y = u.i; - - if (x < 0) - x = INT_MIN - x; - if (y < 0) - y = INT_MIN - y; - - if (abs(x - y) > ulps) - return false; - - return true; -} - static bool compare_uint(unsigned int x, unsigned int y, unsigned int max_diff) { unsigned int diff = x > y ? x - y : y - x; @@ -122,14 +97,6 @@ static bool compare_color(DWORD c1, DWORD c2, BYTE max_diff) && compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff); }
-static bool compare_vec4(const struct vec4 *v1, const struct vec4 *v2, unsigned int ulps) -{ - return compare_float(v1->x, v2->x, ulps) - && compare_float(v1->y, v2->y, ulps) - && compare_float(v1->z, v2->z, ulps) - && compare_float(v1->w, v2->w, ulps); -} - static D3D12_SHADER_BYTECODE shader_bytecode(const DWORD *code, size_t size) { D3D12_SHADER_BYTECODE shader_bytecode = { code, size }; diff --git a/tests/shader_runner.c b/tests/shader_runner.c index ae5daa70b..5af4628eb 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -278,7 +278,7 @@ static void parse_texture_directive(struct texture_params *texture, const char *
static void set_uniforms(struct shader_context *context, size_t offset, size_t count, const void *uniforms) { - context->uniform_count = max(context->uniform_count, offset + count); + context->uniform_count = align(max(context->uniform_count, offset + count), 4); vkd3d_array_reserve((void **)&context->uniforms, &context->uniform_capacity, context->uniform_count, sizeof(*context->uniforms)); memcpy(context->uniforms + offset, uniforms, count * sizeof(*context->uniforms)); @@ -680,9 +680,14 @@ void run_shader_tests(struct shader_context *context, int argc, char **argv, con free(context->textures);
fclose(f); + + vkd3d_test_set_context(NULL); }
START_TEST(shader_runner) { +#ifdef _WIN32 + run_shader_tests_d3d11(argc, argv); +#endif run_shader_tests_d3d12(argc, argv); } diff --git a/tests/shader_runner.h b/tests/shader_runner.h index 9a687edbc..245ef358f 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -16,6 +16,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include <stdint.h> #include "vkd3d_windows.h" #include "vkd3d_d3dcommon.h" #include "vkd3d_d3d12.h" @@ -89,4 +90,7 @@ struct shader_runner_ops
void run_shader_tests(struct shader_context *context, int argc, char **argv, const struct shader_runner_ops *ops);
+#ifdef _WIN32 +void run_shader_tests_d3d11(int argc, char **argv); +#endif void run_shader_tests_d3d12(int argc, char **argv); diff --git a/tests/shader_runner_d3d11.c b/tests/shader_runner_d3d11.c new file mode 100644 index 000000000..d77a4b246 --- /dev/null +++ b/tests/shader_runner_d3d11.c @@ -0,0 +1,639 @@ +/* + * Copyright 2008 Henri Verbeet for CodeWeavers + * Copyright 2015 Józef Kucia for CodeWeavers + * 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 + */ + +#define COBJMACROS +#define CONST_VTABLE +#define VKD3D_TEST_NO_DEFS +#include <d3d11_4.h> +#define __vkd3d_d3dcommon_h__ +#define __vkd3d_dxgibase_h__ +#define __vkd3d_dxgiformat_h__ +#include "vkd3d_d3dcompiler.h" +#include "shader_runner.h" +#include "vkd3d_test.h" + +const GUID IID_IDXGIDevice = {0x54ec77fa, 0x1377, 0x44e6, {0x8c, 0x32, 0x88, 0xfd, 0x5f, 0x44, 0xc8, 0x4c}}; + +static HRESULT (WINAPI *pCreateDXGIFactory1)(REFIID iid, void **factory); + +static HRESULT (WINAPI *pD3D11CreateDevice)(IDXGIAdapter *adapter, D3D_DRIVER_TYPE driver_type, + HMODULE swrast, UINT flags, const D3D_FEATURE_LEVEL *feature_levels, UINT levels, + UINT sdk_version, ID3D11Device **device_out, D3D_FEATURE_LEVEL *obtained_feature_level, + ID3D11DeviceContext **immediate_context); + +struct d3d11_texture +{ + struct texture t; + + ID3D11Texture2D *texture; + ID3D11ShaderResourceView *srv; +}; + +static struct d3d11_texture *d3d11_texture(struct texture *t) +{ + return CONTAINING_RECORD(t, struct d3d11_texture, t); +} + +struct d3d11_shader_context +{ + struct shader_context c; + + ID3D11Device *device; + HWND window; + IDXGISwapChain *swapchain; + ID3D11Texture2D *rt; + ID3D11RenderTargetView *rtv; + ID3D11DeviceContext *immediate_context; + + ID3D11InputLayout *input_layout; + ID3D11VertexShader *vs; + ID3D11Buffer *vb; +}; + +static struct d3d11_shader_context *d3d11_shader_context(struct shader_context *c) +{ + return CONTAINING_RECORD(c, struct d3d11_shader_context, c); +} + +static bool enable_debug_layer; +static bool use_warp_adapter; +static unsigned int use_adapter_idx; + +static ID3D10Blob *compile_shader(const char *source, const char *profile) +{ + ID3D10Blob *blob = NULL, *errors = NULL; + HRESULT hr; + + hr = D3DCompile(source, strlen(source), NULL, NULL, NULL, "main", profile, 0, 0, &blob, &errors); + ok(hr == S_OK, "Failed to compile shader, hr %#lx.\n", hr); + if (errors) + { + if (vkd3d_test_state.debug_level) + trace("%s\n", (char *)ID3D10Blob_GetBufferPointer(errors)); + ID3D10Blob_Release(errors); + } + return blob; +} + +static void parse_args(int argc, char **argv) +{ + unsigned int i; + + for (i = 1; i < argc; ++i) + { + if (!strcmp(argv[i], "--warp")) + use_warp_adapter = true; + else if (!strcmp(argv[i], "--adapter") && i + 1 < argc) + use_adapter_idx = atoi(argv[++i]); + } +} + +static void enable_d3d11_debug_layer(int argc, char **argv) +{ + unsigned int i; + + for (i = 1; i < argc; ++i) + { + if (!strcmp(argv[i], "--validate")) + enable_debug_layer = true; + } +} + +static IDXGIAdapter *create_adapter(void) +{ + IDXGIFactory4 *factory4; + IDXGIFactory *factory; + IDXGIAdapter *adapter; + HRESULT hr; + + if (!pCreateDXGIFactory1) + { + trace("CreateDXGIFactory1() is not available.\n"); + return NULL; + } + + if (FAILED(hr = pCreateDXGIFactory1(&IID_IDXGIFactory, (void **)&factory))) + { + trace("Failed to create IDXGIFactory, hr %#lx.\n", hr); + return NULL; + } + + adapter = NULL; + if (use_warp_adapter) + { + if (SUCCEEDED(hr = IDXGIFactory_QueryInterface(factory, &IID_IDXGIFactory4, (void **)&factory4))) + { + hr = IDXGIFactory4_EnumWarpAdapter(factory4, &IID_IDXGIAdapter, (void **)&adapter); + IDXGIFactory4_Release(factory4); + } + else + { + trace("Failed to get IDXGIFactory4, hr %#lx.\n", hr); + } + } + else + { + hr = IDXGIFactory_EnumAdapters(factory, use_adapter_idx, &adapter); + } + IDXGIFactory_Release(factory); + if (FAILED(hr)) + trace("Failed to get adapter, hr %#lx.\n", hr); + return adapter; +} + +static void init_adapter_info(void) +{ + char name[MEMBER_SIZE(DXGI_ADAPTER_DESC, Description)]; + IDXGIAdapter *adapter; + DXGI_ADAPTER_DESC desc; + unsigned int i; + HRESULT hr; + + if (!(adapter = create_adapter())) + return; + + hr = IDXGIAdapter_GetDesc(adapter, &desc); + ok(hr == S_OK, "Failed to get adapter desc, hr %#lx.\n", hr); + + /* FIXME: Use debugstr_w(). */ + for (i = 0; i < ARRAY_SIZE(desc.Description) && isprint(desc.Description[i]); ++i) + name[i] = desc.Description[i]; + name[min(i, ARRAY_SIZE(name) - 1)] = '\0'; + + trace("Adapter: %s, %04x:%04x.\n", name, desc.VendorId, desc.DeviceId); + + if (desc.VendorId == 0x1414 && desc.DeviceId == 0x008c) + { + trace("Using WARP device.\n"); + use_warp_adapter = true; + } + + IDXGIAdapter_Release(adapter); +} + +static ID3D11Device *create_device(void) +{ + static const D3D_FEATURE_LEVEL feature_level[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + }; + IDXGIAdapter *adapter; + ID3D11Device *device; + UINT flags = 0; + HRESULT hr; + + if (enable_debug_layer) + flags |= D3D11_CREATE_DEVICE_DEBUG; + + if ((adapter = create_adapter())) + { + hr = pD3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, flags, + feature_level, ARRAY_SIZE(feature_level), D3D11_SDK_VERSION, &device, NULL, NULL); + IDXGIAdapter_Release(adapter); + return SUCCEEDED(hr) ? device : NULL; + } + + if (SUCCEEDED(pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, + feature_level, ARRAY_SIZE(feature_level), D3D11_SDK_VERSION, &device, NULL, NULL))) + return device; + if (SUCCEEDED(pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_WARP, NULL, flags, + feature_level, ARRAY_SIZE(feature_level), D3D11_SDK_VERSION, &device, NULL, NULL))) + return device; + if (SUCCEEDED(pD3D11CreateDevice(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, flags, + feature_level, ARRAY_SIZE(feature_level), D3D11_SDK_VERSION, &device, NULL, NULL))) + return device; + + return NULL; +} + +static IDXGISwapChain *create_swapchain(ID3D11Device *device, HWND window) +{ + DXGI_SWAP_CHAIN_DESC dxgi_desc; + IDXGISwapChain *swapchain; + IDXGIDevice *dxgi_device; + IDXGIAdapter *adapter; + IDXGIFactory *factory; + HRESULT hr; + + hr = ID3D11Device_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device); + ok(hr == S_OK, "Failed to get DXGI device, hr %#lx.\n", hr); + hr = IDXGIDevice_GetAdapter(dxgi_device, &adapter); + ok(hr == S_OK, "Failed to get adapter, hr %#lx.\n", hr); + IDXGIDevice_Release(dxgi_device); + hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory); + ok(hr == S_OK, "Failed to get factory, hr %#lx.\n", hr); + IDXGIAdapter_Release(adapter); + + dxgi_desc.BufferDesc.Width = 640; + dxgi_desc.BufferDesc.Height = 480; + dxgi_desc.BufferDesc.RefreshRate.Numerator = 60; + dxgi_desc.BufferDesc.RefreshRate.Denominator = 1; + dxgi_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + dxgi_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + dxgi_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + dxgi_desc.SampleDesc.Count = 1; + dxgi_desc.SampleDesc.Quality = 0; + dxgi_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + dxgi_desc.BufferCount = 1; + dxgi_desc.OutputWindow = window; + dxgi_desc.Windowed = TRUE; + dxgi_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + dxgi_desc.Flags = 0; + + hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &dxgi_desc, &swapchain); + ok(hr == S_OK, "Failed to create swapchain, hr %#lx.\n", hr); + IDXGIFactory_Release(factory); + + return swapchain; +} + +static BOOL init_test_context(struct d3d11_shader_context *context) +{ + const D3D11_TEXTURE2D_DESC texture_desc = + { + .Width = 640, + .Height = 480, + .MipLevels = 1, + .ArraySize = 1, + .Format = DXGI_FORMAT_R32G32B32A32_FLOAT, + .SampleDesc.Count = 1, + .Usage = D3D11_USAGE_DEFAULT, + .BindFlags = D3D11_BIND_RENDER_TARGET, + }; + unsigned int rt_width, rt_height; + D3D11_VIEWPORT vp; + HRESULT hr; + RECT rect; + + memset(context, 0, sizeof(*context)); + + if (!(context->device = create_device())) + { + skip("Failed to create device.\n"); + return FALSE; + } + + rt_width = 640; + rt_height = 480; + SetRect(&rect, 0, 0, rt_width, rt_height); + AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE); + context->window = CreateWindowA("static", "d3dcompiler_test", WS_OVERLAPPEDWINDOW, + 0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, NULL); + context->swapchain = create_swapchain(context->device, context->window); + + hr = ID3D11Device_CreateTexture2D(context->device, &texture_desc, NULL, &context->rt); + ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr); + + hr = ID3D11Device_CreateRenderTargetView(context->device, (ID3D11Resource *)context->rt, NULL, &context->rtv); + ok(hr == S_OK, "Failed to create rendertarget view, hr %#lx.\n", hr); + + ID3D11Device_GetImmediateContext(context->device, &context->immediate_context); + + ID3D11DeviceContext_OMSetRenderTargets(context->immediate_context, 1, &context->rtv, NULL); + + vp.TopLeftX = 0.0f; + vp.TopLeftY = 0.0f; + vp.Width = rt_width; + vp.Height = rt_height; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + ID3D11DeviceContext_RSSetViewports(context->immediate_context, 1, &vp); + + return TRUE; +} + +static void destroy_test_context(struct d3d11_shader_context *context) +{ + ULONG ref; + + if (context->input_layout) + ID3D11InputLayout_Release(context->input_layout); + if (context->vs) + ID3D11VertexShader_Release(context->vs); + if (context->vb) + ID3D11Buffer_Release(context->vb); + + ID3D11DeviceContext_Release(context->immediate_context); + ID3D11RenderTargetView_Release(context->rtv); + ID3D11Texture2D_Release(context->rt); + IDXGISwapChain_Release(context->swapchain); + DestroyWindow(context->window); + + ref = ID3D11Device_Release(context->device); + ok(!ref, "Device has %lu references left.\n", ref); +} + +static ID3D11Buffer *create_buffer(ID3D11Device *device, unsigned int bind_flags, unsigned int size, const void *data) +{ + D3D11_SUBRESOURCE_DATA resource_data; + D3D11_BUFFER_DESC buffer_desc; + ID3D11Buffer *buffer; + HRESULT hr; + + buffer_desc.ByteWidth = size; + buffer_desc.Usage = D3D11_USAGE_DEFAULT; + buffer_desc.BindFlags = bind_flags; + buffer_desc.CPUAccessFlags = 0; + buffer_desc.MiscFlags = 0; + buffer_desc.StructureByteStride = 0; + + resource_data.pSysMem = data; + resource_data.SysMemPitch = 0; + resource_data.SysMemSlicePitch = 0; + + hr = ID3D11Device_CreateBuffer(device, &buffer_desc, data ? &resource_data : NULL, &buffer); + ok(hr == S_OK, "Failed to create buffer, hr %#lx.\n", hr); + return buffer; +} + +static struct texture *d3d11_runner_create_texture(struct shader_context *c, const struct texture_params *params) +{ + struct d3d11_shader_context *context = d3d11_shader_context(c); + ID3D11Device *device = context->device; + D3D11_SUBRESOURCE_DATA resource_data; + D3D11_TEXTURE2D_DESC desc = {0}; + struct d3d11_texture *texture; + HRESULT hr; + + texture = calloc(1, sizeof(*texture)); + + texture->t.slot = params->slot; + + desc.Width = params->width; + desc.Height = params->height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = params->format; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + + resource_data.pSysMem = params->data; + resource_data.SysMemPitch = params->width * params->texel_size; + resource_data.SysMemSlicePitch = params->height * resource_data.SysMemPitch; + + hr = ID3D11Device_CreateTexture2D(device, &desc, &resource_data, &texture->texture); + ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr); + hr = ID3D11Device_CreateShaderResourceView(device, + (ID3D11Resource *)texture->texture, NULL, &texture->srv); + ok(hr == S_OK, "Failed to create shader resource view, hr %#lx.\n", hr); + + return &texture->t; +} + +static void d3d11_runner_destroy_texture(struct shader_context *c, struct texture *t) +{ + struct d3d11_texture *texture = d3d11_texture(t); + + ID3D11Texture2D_Release(texture->texture); + ID3D11ShaderResourceView_Release(texture->srv); + free(texture); +} + +static void d3d11_runner_draw_quad(struct shader_context *c) +{ + static const D3D11_INPUT_ELEMENT_DESC default_layout_desc[] = + { + {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, + }; + + static const char vs_source[] = + "float4 main(float4 position : POSITION) : sv_position\n" + "{\n" + " return position;\n" + "}"; + + static const struct vec2 quad[] = + { + {-1.0f, -1.0f}, + {-1.0f, 1.0f}, + { 1.0f, -1.0f}, + { 1.0f, 1.0f}, + }; + + struct d3d11_shader_context *context = d3d11_shader_context(c); + ID3D11Device *device = context->device; + unsigned int stride, offset; + ID3D11Buffer *cb = NULL; + ID3D11PixelShader *ps; + ID3D10Blob *ps_code; + unsigned int i; + HRESULT hr; + + static const char *const ps_profiles[] = + { + [SHADER_MODEL_4_0] = "ps_4_0", + [SHADER_MODEL_4_1] = "ps_4_1", + [SHADER_MODEL_5_0] = "ps_5_0", + [SHADER_MODEL_5_1] = "ps_5_1", + }; + + if (!(ps_code = compile_shader(context->c.ps_source, ps_profiles[context->c.minimum_shader_model]))) + return; + + if (!context->input_layout || !context->vs) + { + ID3D10Blob *vs_code = compile_shader(vs_source, "vs_4_0"); + + if (!context->input_layout) + { + hr = ID3D11Device_CreateInputLayout(device, default_layout_desc, ARRAY_SIZE(default_layout_desc), + ID3D10Blob_GetBufferPointer(vs_code), ID3D10Blob_GetBufferSize(vs_code), &context->input_layout); + ok(hr == S_OK, "Failed to create input layout, hr %#lx.\n", hr); + } + + if (!context->vs) + { + hr = ID3D11Device_CreateVertexShader(device, ID3D10Blob_GetBufferPointer(vs_code), + ID3D10Blob_GetBufferSize(vs_code), NULL, &context->vs); + ok(hr == S_OK, "Failed to create vertex shader, hr %#lx.\n", hr); + } + + ID3D10Blob_Release(vs_code); + } + + if (!context->vb) + context->vb = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, sizeof(quad), quad); + + hr = ID3D11Device_CreatePixelShader(device, ID3D10Blob_GetBufferPointer(ps_code), + ID3D10Blob_GetBufferSize(ps_code), NULL, &ps); + ok(hr == S_OK, "Failed to create pixel shader, hr %#lx.\n", hr); + + if (context->c.uniform_count) + { + cb = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, + context->c.uniform_count * sizeof(*context->c.uniforms), context->c.uniforms); + ID3D11DeviceContext_PSSetConstantBuffers(context->immediate_context, 0, 1, &cb); + } + + for (i = 0; i < context->c.texture_count; ++i) + { + struct d3d11_texture *texture = d3d11_texture(context->c.textures[i]); + + ID3D11DeviceContext_PSSetShaderResources(context->immediate_context, texture->t.slot, 1, &texture->srv); + } + + for (i = 0; i < context->c.sampler_count; ++i) + { + struct sampler *sampler = &context->c.samplers[i]; + ID3D11SamplerState *d3d11_sampler; + D3D11_SAMPLER_DESC desc = {0}; + + /* Members of D3D11_FILTER are compatible with D3D12_FILTER. */ + desc.Filter = (D3D11_FILTER)sampler->filter; + /* Members of D3D11_TEXTURE_ADDRESS_MODE are compatible with D3D12_TEXTURE_ADDRESS_MODE. */ + desc.AddressU = (D3D11_TEXTURE_ADDRESS_MODE)sampler->u_address; + desc.AddressV = (D3D11_TEXTURE_ADDRESS_MODE)sampler->v_address; + desc.AddressW = (D3D11_TEXTURE_ADDRESS_MODE)sampler->w_address; + desc.ComparisonFunc = D3D11_COMPARISON_NEVER; + desc.MaxLOD = D3D11_FLOAT32_MAX; + + hr = ID3D11Device_CreateSamplerState(device, &desc, &d3d11_sampler); + ok(hr == S_OK, "Failed to create sampler state, hr %#lx.\n", hr); + ID3D11DeviceContext_PSSetSamplers(context->immediate_context, sampler->slot, 1, &d3d11_sampler); + ID3D11SamplerState_Release(d3d11_sampler); + } + + ID3D11DeviceContext_IASetInputLayout(context->immediate_context, context->input_layout); + ID3D11DeviceContext_IASetPrimitiveTopology(context->immediate_context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + stride = sizeof(*quad); + offset = 0; + ID3D11DeviceContext_IASetVertexBuffers(context->immediate_context, 0, 1, &context->vb, &stride, &offset); + ID3D11DeviceContext_VSSetShader(context->immediate_context, context->vs, NULL, 0); + ID3D11DeviceContext_PSSetShader(context->immediate_context, ps, NULL, 0); + + ID3D11DeviceContext_Draw(context->immediate_context, 4, 0); + + ID3D11PixelShader_Release(ps); + if (cb) + ID3D11Buffer_Release(cb); +} + +struct resource_readback +{ + uint64_t width; + unsigned int height; + ID3D11Resource *resource; + D3D11_MAPPED_SUBRESOURCE map_desc; +}; + +static void init_readback(struct d3d11_shader_context *context, struct resource_readback *rb) +{ + D3D11_TEXTURE2D_DESC texture_desc; + HRESULT hr; + + ID3D11Texture2D_GetDesc(context->rt, &texture_desc); + texture_desc.Usage = D3D11_USAGE_STAGING; + texture_desc.BindFlags = 0; + texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + texture_desc.MiscFlags = 0; + hr = ID3D11Device_CreateTexture2D(context->device, &texture_desc, NULL, (ID3D11Texture2D **)&rb->resource); + ok(hr == S_OK, "Failed to create texture, hr %#lx.\n", hr); + + ID3D11DeviceContext_CopyResource(context->immediate_context, rb->resource, (ID3D11Resource *)context->rt); + hr = ID3D11DeviceContext_Map(context->immediate_context, rb->resource, 0, D3D11_MAP_READ, 0, &rb->map_desc); + ok(hr == S_OK, "Failed to map texture, hr %#lx.\n", hr); + + rb->width = texture_desc.Width; + rb->height = texture_desc.Height; +} + +static void release_readback(struct d3d11_shader_context *context, struct resource_readback *rb) +{ + ID3D11DeviceContext_Unmap(context->immediate_context, rb->resource, 0); + ID3D11Resource_Release(rb->resource); +} + +static const struct vec4 *get_readback_vec4(struct resource_readback *rb, unsigned int x, unsigned int y) +{ + return (struct vec4 *)((BYTE *)rb->map_desc.pData + y * rb->map_desc.RowPitch) + x; +} + +static void check_readback_data_vec4(struct resource_readback *rb, + const RECT *rect, const struct vec4 *expected, unsigned int max_diff) +{ + RECT r = {0, 0, rb->width, rb->height}; + unsigned int x = 0, y = 0; + struct vec4 got = {0}; + bool all_match = true; + + if (rect) + r = *rect; + + for (y = r.top; y < r.bottom; ++y) + { + for (x = r.left; x < r.right; ++x) + { + got = *get_readback_vec4(rb, x, y); + if (!compare_vec4(&got, expected, max_diff)) + { + all_match = false; + break; + } + } + if (!all_match) + break; + } + ok(all_match, "Got {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e} at (%u, %u).\n", + got.x, got.y, got.z, got.w, expected->x, expected->y, expected->z, expected->w, x, y); +} + +static void d3d11_runner_probe_vec4(struct shader_context *c, const RECT *rect, const struct vec4 *v, unsigned int ulps) +{ + struct d3d11_shader_context *context = d3d11_shader_context(c); + struct resource_readback rb; + + init_readback(context, &rb); + check_readback_data_vec4(&rb, rect, v, ulps); + release_readback(context, &rb); +} + +static const struct shader_runner_ops d3d11_runner_ops = +{ + .create_texture = d3d11_runner_create_texture, + .destroy_texture = d3d11_runner_destroy_texture, + .draw_quad = d3d11_runner_draw_quad, + .probe_vec4 = d3d11_runner_probe_vec4, +}; + +void run_shader_tests_d3d11(int argc, char **argv) +{ + HMODULE dxgi_module, d3d11_module; + struct d3d11_shader_context context; + + d3d11_module = LoadLibraryA("d3d11.dll"); + dxgi_module = LoadLibraryA("dxgi.dll"); + if (d3d11_module && dxgi_module) + { + pCreateDXGIFactory1 = (void *)GetProcAddress(dxgi_module, "CreateDXGIFactory1"); + pD3D11CreateDevice = (void *)GetProcAddress(d3d11_module, "D3D11CreateDevice"); + + parse_args(argc, argv); + enable_d3d11_debug_layer(argc, argv); + init_adapter_info(); + init_test_context(&context); + run_shader_tests(&context.c, argc, argv, &d3d11_runner_ops); + destroy_test_context(&context); + } + FreeLibrary(d3d11_module); + FreeLibrary(dxgi_module); +} diff --git a/tests/utils.h b/tests/utils.h index 825520c27..530a3cee7 100644 --- a/tests/utils.h +++ b/tests/utils.h @@ -19,9 +19,15 @@ #ifndef __VKD3D_TEST_UTILS_H #define __VKD3D_TEST_UTILS_H
+#include <limits.h> #include <stdbool.h> #include <stdlib.h>
+struct vec2 +{ + float x, y; +}; + struct vec4 { float x, y, z, w; @@ -55,4 +61,37 @@ static inline bool vkd3d_array_reserve(void **elements, size_t *capacity, size_t return true; }
+static bool compare_float(float f, float g, unsigned int ulps) +{ + int x, y; + union + { + float f; + int i; + } u; + + u.f = f; + x = u.i; + u.f = g; + y = u.i; + + if (x < 0) + x = INT_MIN - x; + if (y < 0) + y = INT_MIN - y; + + if (abs(x - y) > ulps) + return false; + + return true; +} + +static inline bool compare_vec4(const struct vec4 *v1, const struct vec4 *v2, unsigned int ulps) +{ + return compare_float(v1->x, v2->x, ulps) + && compare_float(v1->y, v2->y, ulps) + && compare_float(v1->z, v2->z, ulps) + && compare_float(v1->w, v2->w, ulps); +} + #endif
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com