mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-01-28 13:05:02 -08:00
tests: Introduce a custom format and parser for shader-based tests.
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d64a423233
commit
68ef1de6ec
18
Makefile.am
18
Makefile.am
@ -46,6 +46,9 @@ vkd3d_cross_tests = \
|
|||||||
tests/d3d12 \
|
tests/d3d12 \
|
||||||
tests/d3d12_invalid_usage
|
tests/d3d12_invalid_usage
|
||||||
|
|
||||||
|
vkd3d_shader_runners = \
|
||||||
|
tests/shader_runner_d3d12
|
||||||
|
|
||||||
vkd3d_test_headers = \
|
vkd3d_test_headers = \
|
||||||
tests/d3d12_crosstest.h \
|
tests/d3d12_crosstest.h \
|
||||||
tests/d3d12_test_utils.h
|
tests/d3d12_test_utils.h
|
||||||
@ -151,13 +154,18 @@ vkd3d_compiler_LDADD = libvkd3d-shader.la @NCURSES_LIBS@
|
|||||||
|
|
||||||
LDADD = libvkd3d.la libvkd3d-utils.la
|
LDADD = libvkd3d.la libvkd3d-utils.la
|
||||||
AM_DEFAULT_SOURCE_EXT = .c
|
AM_DEFAULT_SOURCE_EXT = .c
|
||||||
|
|
||||||
|
TEST_EXTENSIONS = .shader_test
|
||||||
|
|
||||||
if BUILD_TESTS
|
if BUILD_TESTS
|
||||||
check_PROGRAMS = $(vkd3d_tests) $(vkd3d_cross_tests)
|
check_PROGRAMS = $(vkd3d_tests) $(vkd3d_cross_tests) $(vkd3d_shader_runners)
|
||||||
TESTS = $(vkd3d_tests) $(vkd3d_cross_tests)
|
TESTS = $(vkd3d_tests) $(vkd3d_cross_tests)
|
||||||
tests_d3d12_LDADD = $(LDADD) @PTHREAD_LIBS@ @VULKAN_LIBS@
|
tests_d3d12_LDADD = $(LDADD) @PTHREAD_LIBS@ @VULKAN_LIBS@
|
||||||
tests_d3d12_invalid_usage_LDADD = $(LDADD) @VULKAN_LIBS@
|
tests_d3d12_invalid_usage_LDADD = $(LDADD) @VULKAN_LIBS@
|
||||||
|
tests_shader_runner_d3d12_LDADD = $(LDADD) @VULKAN_LIBS@
|
||||||
tests_vkd3d_api_LDADD = libvkd3d.la @VULKAN_LIBS@
|
tests_vkd3d_api_LDADD = libvkd3d.la @VULKAN_LIBS@
|
||||||
tests_vkd3d_shader_api_LDADD = libvkd3d-shader.la
|
tests_vkd3d_shader_api_LDADD = libvkd3d-shader.la
|
||||||
|
SHADER_TEST_LOG_COMPILER = tests/shader_runner_d3d12
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_DEMOS
|
if BUILD_DEMOS
|
||||||
@ -239,7 +247,7 @@ if HAVE_CROSSTARGET32
|
|||||||
CROSS32_CC = @CROSSCC32@
|
CROSS32_CC = @CROSSCC32@
|
||||||
CROSS32_DLLTOOL = @CROSSTARGET32@-dlltool
|
CROSS32_DLLTOOL = @CROSSTARGET32@-dlltool
|
||||||
CROSS32_IMPLIBS = $(cross_implibs:=.cross32.a)
|
CROSS32_IMPLIBS = $(cross_implibs:=.cross32.a)
|
||||||
CROSS32_EXEFILES = $(vkd3d_cross_tests:=.cross32.exe) $(vkd3d_demos:=.cross32.exe)
|
CROSS32_EXEFILES = $(vkd3d_cross_tests:=.cross32.exe) $(vkd3d_demos:=.cross32.exe) $(vkd3d_shader_runners:=.cross32.exe)
|
||||||
CROSS32_FILES = $(CROSS32_IMPLIBS) $(CROSS32_EXEFILES)
|
CROSS32_FILES = $(CROSS32_IMPLIBS) $(CROSS32_EXEFILES)
|
||||||
|
|
||||||
CLEANFILES += $(CROSS32_FILES)
|
CLEANFILES += $(CROSS32_FILES)
|
||||||
@ -254,7 +262,7 @@ $(CROSS32_IMPLIBS): %.cross32.a: %.cross32.def
|
|||||||
|
|
||||||
$(CROSS32_EXEFILES): %.cross32.exe: %.c $(CROSS32_IMPLIBS) $(widl_headers)
|
$(CROSS32_EXEFILES): %.cross32.exe: %.c $(CROSS32_IMPLIBS) $(widl_headers)
|
||||||
$(AM_V_CCLD)depbase=`echo $@ | $(SED) 's![^/]*$$!$(DEPDIR)/&!;s!\.exe$$!!'`; \
|
$(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 && \
|
$(CROSS32_CC) $(CROSS_CFLAGS) -MT $@ -MD -MP -MF $$depbase.Tpo -o $@ $< $(CROSS32_IMPLIBS) -ldxgi -lgdi32 -ld3dcompiler_47 && \
|
||||||
$(am__mv) $$depbase.Tpo $$depbase.Po
|
$(am__mv) $$depbase.Tpo $$depbase.Po
|
||||||
else
|
else
|
||||||
crosstest32:
|
crosstest32:
|
||||||
@ -264,7 +272,7 @@ if HAVE_CROSSTARGET64
|
|||||||
CROSS64_CC = @CROSSCC64@
|
CROSS64_CC = @CROSSCC64@
|
||||||
CROSS64_DLLTOOL = @CROSSTARGET64@-dlltool
|
CROSS64_DLLTOOL = @CROSSTARGET64@-dlltool
|
||||||
CROSS64_IMPLIBS = $(cross_implibs:=.cross64.a)
|
CROSS64_IMPLIBS = $(cross_implibs:=.cross64.a)
|
||||||
CROSS64_EXEFILES = $(vkd3d_cross_tests:=.cross64.exe) $(vkd3d_demos:=.cross64.exe)
|
CROSS64_EXEFILES = $(vkd3d_cross_tests:=.cross64.exe) $(vkd3d_demos:=.cross64.exe) $(vkd3d_shader_runners:=.cross64.exe)
|
||||||
CROSS64_FILES = $(CROSS64_IMPLIBS) $(CROSS64_EXEFILES)
|
CROSS64_FILES = $(CROSS64_IMPLIBS) $(CROSS64_EXEFILES)
|
||||||
|
|
||||||
CLEANFILES += $(CROSS64_FILES)
|
CLEANFILES += $(CROSS64_FILES)
|
||||||
@ -279,7 +287,7 @@ $(CROSS64_IMPLIBS): %.cross64.a: %.cross64.def
|
|||||||
|
|
||||||
$(CROSS64_EXEFILES): %.cross64.exe: %.c $(CROSS64_IMPLIBS) $(widl_headers)
|
$(CROSS64_EXEFILES): %.cross64.exe: %.c $(CROSS64_IMPLIBS) $(widl_headers)
|
||||||
$(AM_V_CCLD)depbase=`echo $@ | sed 's![^/]*$$!$(DEPDIR)/&!;s!\.exe$$!!'`; \
|
$(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 && \
|
$(CROSS64_CC) $(CROSS_CFLAGS) -MT $@ -MD -MP -MF $$depbase.Tpo -o $@ $< $(CROSS64_IMPLIBS) -ldxgi -lgdi32 -ld3dcompiler_47 && \
|
||||||
$(am__mv) $$depbase.Tpo $$depbase.Po
|
$(am__mv) $$depbase.Tpo $$depbase.Po
|
||||||
else
|
else
|
||||||
crosstest64:
|
crosstest64:
|
||||||
|
1
tests/.gitignore
vendored
1
tests/.gitignore
vendored
@ -1,5 +1,6 @@
|
|||||||
/d3d12
|
/d3d12
|
||||||
/d3d12_invalid_usage
|
/d3d12_invalid_usage
|
||||||
|
/shader_runner_d3d12
|
||||||
/vkd3d_api
|
/vkd3d_api
|
||||||
/vkd3d_common
|
/vkd3d_common
|
||||||
/vkd3d_shader_api
|
/vkd3d_shader_api
|
||||||
|
101
tests/d3d12.c
101
tests/d3d12.c
@ -31,11 +31,6 @@ struct vec2
|
|||||||
float x, y;
|
float x, y;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vec4
|
|
||||||
{
|
|
||||||
float x, y, z, w;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct uvec4
|
struct uvec4
|
||||||
{
|
{
|
||||||
unsigned int x, y, z, w;
|
unsigned int x, y, z, w;
|
||||||
@ -46,39 +41,6 @@ struct ivec4
|
|||||||
int x, y, z, w;
|
int x, y, z, w;
|
||||||
};
|
};
|
||||||
|
|
||||||
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_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 bool compare_uvec4(const struct uvec4* v1, const struct uvec4 *v2)
|
static bool compare_uvec4(const struct uvec4* v1, const struct uvec4 *v2)
|
||||||
{
|
{
|
||||||
return v1->x == v2->x && v1->y == v2->y && v1->z == v2->z && v1->w == v2->w;
|
return v1->x == v2->x && v1->y == v2->y && v1->z == v2->z && v1->w == v2->w;
|
||||||
@ -408,11 +370,6 @@ static float get_readback_float(struct resource_readback *rb, unsigned int x, un
|
|||||||
return *(float *)get_readback_data(rb, x, y, 0, sizeof(float));
|
return *(float *)get_readback_data(rb, x, y, 0, sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct vec4 *get_readback_vec4(struct resource_readback *rb, unsigned int x, unsigned int y)
|
|
||||||
{
|
|
||||||
return get_readback_data(rb, x, y, 0, sizeof(struct vec4));
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct uvec4 *get_readback_uvec4(struct resource_readback *rb, unsigned int x, unsigned int y)
|
static const struct uvec4 *get_readback_uvec4(struct resource_readback *rb, unsigned int x, unsigned int y)
|
||||||
{
|
{
|
||||||
return get_readback_data(rb, x, y, 0, sizeof(struct uvec4));
|
return get_readback_data(rb, x, y, 0, sizeof(struct uvec4));
|
||||||
@ -582,37 +539,6 @@ static void check_sub_resource_uint64_(unsigned int line, ID3D12Resource *textur
|
|||||||
release_resource_readback(&rb);
|
release_resource_readback(&rb);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define check_sub_resource_vec4(a, b, c, d, e, f) check_sub_resource_vec4_(__LINE__, a, b, c, d, e, f)
|
|
||||||
static void check_sub_resource_vec4_(unsigned int line, ID3D12Resource *texture,
|
|
||||||
unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list,
|
|
||||||
const struct vec4 *expected, unsigned int max_diff)
|
|
||||||
{
|
|
||||||
struct resource_readback rb;
|
|
||||||
unsigned int x = 0, y;
|
|
||||||
bool all_match = true;
|
|
||||||
struct vec4 got = {0};
|
|
||||||
|
|
||||||
get_texture_readback_with_command_list(texture, sub_resource_idx, &rb, queue, command_list);
|
|
||||||
for (y = 0; y < rb.height; ++y)
|
|
||||||
{
|
|
||||||
for (x = 0; x < rb.width; ++x)
|
|
||||||
{
|
|
||||||
got = *get_readback_vec4(&rb, x, y);
|
|
||||||
if (!compare_vec4(&got, expected, max_diff))
|
|
||||||
{
|
|
||||||
all_match = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!all_match)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
release_resource_readback(&rb);
|
|
||||||
|
|
||||||
ok_(line)(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define check_sub_resource_uvec4(a, b, c, d, e) check_sub_resource_uvec4_(__LINE__, a, b, c, d, e)
|
#define check_sub_resource_uvec4(a, b, c, d, e) check_sub_resource_uvec4_(__LINE__, a, b, c, d, e)
|
||||||
static void check_sub_resource_uvec4_(unsigned int line, ID3D12Resource *texture,
|
static void check_sub_resource_uvec4_(unsigned int line, ID3D12Resource *texture,
|
||||||
unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list,
|
unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list,
|
||||||
@ -750,33 +676,6 @@ static ID3D12RootSignature *create_cb_root_signature_(unsigned int line,
|
|||||||
return root_signature;
|
return root_signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define create_32bit_constants_root_signature(a, b, c, e) \
|
|
||||||
create_32bit_constants_root_signature_(__LINE__, a, b, c, e, 0)
|
|
||||||
static ID3D12RootSignature *create_32bit_constants_root_signature_(unsigned int line,
|
|
||||||
ID3D12Device *device, unsigned int reg_idx, unsigned int element_count,
|
|
||||||
D3D12_SHADER_VISIBILITY shader_visibility, D3D12_ROOT_SIGNATURE_FLAGS flags)
|
|
||||||
{
|
|
||||||
D3D12_ROOT_SIGNATURE_DESC root_signature_desc;
|
|
||||||
ID3D12RootSignature *root_signature = NULL;
|
|
||||||
D3D12_ROOT_PARAMETER root_parameter;
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
root_parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
|
|
||||||
root_parameter.Constants.ShaderRegister = reg_idx;
|
|
||||||
root_parameter.Constants.RegisterSpace = 0;
|
|
||||||
root_parameter.Constants.Num32BitValues = element_count;
|
|
||||||
root_parameter.ShaderVisibility = shader_visibility;
|
|
||||||
|
|
||||||
memset(&root_signature_desc, 0, sizeof(root_signature_desc));
|
|
||||||
root_signature_desc.NumParameters = 1;
|
|
||||||
root_signature_desc.pParameters = &root_parameter;
|
|
||||||
root_signature_desc.Flags = flags;
|
|
||||||
hr = create_root_signature(device, &root_signature_desc, &root_signature);
|
|
||||||
ok_(line)(SUCCEEDED(hr), "Failed to create root signature, hr %#x.\n", hr);
|
|
||||||
|
|
||||||
return root_signature;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define create_texture_root_signature(a, b, c, d) create_texture_root_signature_(__LINE__, a, b, c, d, NULL)
|
#define create_texture_root_signature(a, b, c, d) create_texture_root_signature_(__LINE__, a, b, c, d, NULL)
|
||||||
static ID3D12RootSignature *create_texture_root_signature_(unsigned int line,
|
static ID3D12RootSignature *create_texture_root_signature_(unsigned int line,
|
||||||
ID3D12Device *device, D3D12_SHADER_VISIBILITY shader_visibility,
|
ID3D12Device *device, D3D12_SHADER_VISIBILITY shader_visibility,
|
||||||
|
@ -46,6 +46,7 @@ typedef int HRESULT;
|
|||||||
#define WIDL_C_INLINE_WRAPPERS
|
#define WIDL_C_INLINE_WRAPPERS
|
||||||
#include "vkd3d_d3d12.h"
|
#include "vkd3d_d3d12.h"
|
||||||
#include "vkd3d_d3d12sdklayers.h"
|
#include "vkd3d_d3d12sdklayers.h"
|
||||||
|
#include "vkd3d_d3dcompiler.h"
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
@ -19,6 +19,11 @@
|
|||||||
#ifndef __VKD3D_D3D12_TEST_UTILS_H
|
#ifndef __VKD3D_D3D12_TEST_UTILS_H
|
||||||
#define __VKD3D_D3D12_TEST_UTILS_H
|
#define __VKD3D_D3D12_TEST_UTILS_H
|
||||||
|
|
||||||
|
struct vec4
|
||||||
|
{
|
||||||
|
float x, y, z, w;
|
||||||
|
};
|
||||||
|
|
||||||
#define wait_queue_idle(a, b) wait_queue_idle_(__LINE__, a, b)
|
#define wait_queue_idle(a, b) wait_queue_idle_(__LINE__, a, b)
|
||||||
static void wait_queue_idle_(unsigned int line, ID3D12Device *device, ID3D12CommandQueue *queue);
|
static void wait_queue_idle_(unsigned int line, ID3D12Device *device, ID3D12CommandQueue *queue);
|
||||||
static ID3D12Device *create_device(void);
|
static ID3D12Device *create_device(void);
|
||||||
@ -53,6 +58,31 @@ static void set_viewport(D3D12_VIEWPORT *vp, float x, float y,
|
|||||||
vp->MaxDepth = max_depth;
|
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)
|
static bool compare_uint(unsigned int x, unsigned int y, unsigned int max_diff)
|
||||||
{
|
{
|
||||||
unsigned int diff = x > y ? x - y : y - x;
|
unsigned int diff = x > y ? x - y : y - x;
|
||||||
@ -68,6 +98,14 @@ static bool compare_color(DWORD c1, DWORD c2, BYTE max_diff)
|
|||||||
&& compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, 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)
|
static D3D12_SHADER_BYTECODE shader_bytecode(const DWORD *code, size_t size)
|
||||||
{
|
{
|
||||||
D3D12_SHADER_BYTECODE shader_bytecode = { code, size };
|
D3D12_SHADER_BYTECODE shader_bytecode = { code, size };
|
||||||
@ -501,6 +539,11 @@ static unsigned int get_readback_uint(struct resource_readback *rb,
|
|||||||
return *(unsigned int *)get_readback_data(rb, x, y, z, sizeof(unsigned int));
|
return *(unsigned int *)get_readback_data(rb, x, y, z, sizeof(unsigned int));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct vec4 *get_readback_vec4(struct resource_readback *rb, unsigned int x, unsigned int y)
|
||||||
|
{
|
||||||
|
return get_readback_data(rb, x, y, 0, sizeof(struct vec4));
|
||||||
|
}
|
||||||
|
|
||||||
static void release_resource_readback(struct resource_readback *rb)
|
static void release_resource_readback(struct resource_readback *rb)
|
||||||
{
|
{
|
||||||
D3D12_RANGE range = {0, 0};
|
D3D12_RANGE range = {0, 0};
|
||||||
@ -554,6 +597,37 @@ static inline void check_sub_resource_uint_(unsigned int line, ID3D12Resource *t
|
|||||||
release_resource_readback(&rb);
|
release_resource_readback(&rb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define check_sub_resource_vec4(a, b, c, d, e, f) check_sub_resource_vec4_(__LINE__, a, b, c, d, e, f)
|
||||||
|
static inline void check_sub_resource_vec4_(unsigned int line, ID3D12Resource *texture,
|
||||||
|
unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list,
|
||||||
|
const struct vec4 *expected, unsigned int max_diff)
|
||||||
|
{
|
||||||
|
struct resource_readback rb;
|
||||||
|
unsigned int x = 0, y;
|
||||||
|
bool all_match = true;
|
||||||
|
struct vec4 got = {0};
|
||||||
|
|
||||||
|
get_texture_readback_with_command_list(texture, sub_resource_idx, &rb, queue, command_list);
|
||||||
|
for (y = 0; y < rb.height; ++y)
|
||||||
|
{
|
||||||
|
for (x = 0; x < rb.width; ++x)
|
||||||
|
{
|
||||||
|
got = *get_readback_vec4(&rb, x, y);
|
||||||
|
if (!compare_vec4(&got, expected, max_diff))
|
||||||
|
{
|
||||||
|
all_match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!all_match)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
release_resource_readback(&rb);
|
||||||
|
|
||||||
|
ok_(line)(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);
|
||||||
|
}
|
||||||
|
|
||||||
#define create_default_buffer(a, b, c, d) create_default_buffer_(__LINE__, a, b, c, d)
|
#define create_default_buffer(a, b, c, d) create_default_buffer_(__LINE__, a, b, c, d)
|
||||||
static inline ID3D12Resource *create_default_buffer_(unsigned int line, ID3D12Device *device,
|
static inline ID3D12Resource *create_default_buffer_(unsigned int line, ID3D12Device *device,
|
||||||
size_t size, D3D12_RESOURCE_FLAGS resource_flags, D3D12_RESOURCE_STATES initial_resource_state)
|
size_t size, D3D12_RESOURCE_FLAGS resource_flags, D3D12_RESOURCE_STATES initial_resource_state)
|
||||||
@ -595,7 +669,7 @@ static ID3D12Resource *create_default_texture_(unsigned int line, ID3D12Device *
|
|||||||
|
|
||||||
#define create_default_texture(a, b, c, d, e, f) create_default_texture2d_(__LINE__, a, b, c, 1, 1, d, e, f)
|
#define create_default_texture(a, b, c, d, e, f) create_default_texture2d_(__LINE__, a, b, c, 1, 1, d, e, f)
|
||||||
#define create_default_texture2d(a, b, c, d, e, f, g, h) create_default_texture2d_(__LINE__, a, b, c, d, e, f, g, h)
|
#define create_default_texture2d(a, b, c, d, e, f, g, h) create_default_texture2d_(__LINE__, a, b, c, d, e, f, g, h)
|
||||||
static ID3D12Resource *create_default_texture2d_(unsigned int line, ID3D12Device *device,
|
static inline ID3D12Resource *create_default_texture2d_(unsigned int line, ID3D12Device *device,
|
||||||
unsigned int width, unsigned int height, unsigned int array_size, unsigned int miplevel_count,
|
unsigned int width, unsigned int height, unsigned int array_size, unsigned int miplevel_count,
|
||||||
DXGI_FORMAT format, D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_STATES initial_state)
|
DXGI_FORMAT format, D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_STATES initial_state)
|
||||||
{
|
{
|
||||||
@ -646,6 +720,33 @@ static ID3D12RootSignature *create_empty_root_signature_(unsigned int line,
|
|||||||
return root_signature;
|
return root_signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define create_32bit_constants_root_signature(a, b, c, e) \
|
||||||
|
create_32bit_constants_root_signature_(__LINE__, a, b, c, e, 0)
|
||||||
|
static inline ID3D12RootSignature *create_32bit_constants_root_signature_(unsigned int line,
|
||||||
|
ID3D12Device *device, unsigned int reg_idx, unsigned int element_count,
|
||||||
|
D3D12_SHADER_VISIBILITY shader_visibility, D3D12_ROOT_SIGNATURE_FLAGS flags)
|
||||||
|
{
|
||||||
|
D3D12_ROOT_SIGNATURE_DESC root_signature_desc;
|
||||||
|
ID3D12RootSignature *root_signature = NULL;
|
||||||
|
D3D12_ROOT_PARAMETER root_parameter;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
root_parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
|
||||||
|
root_parameter.Constants.ShaderRegister = reg_idx;
|
||||||
|
root_parameter.Constants.RegisterSpace = 0;
|
||||||
|
root_parameter.Constants.Num32BitValues = element_count;
|
||||||
|
root_parameter.ShaderVisibility = shader_visibility;
|
||||||
|
|
||||||
|
memset(&root_signature_desc, 0, sizeof(root_signature_desc));
|
||||||
|
root_signature_desc.NumParameters = 1;
|
||||||
|
root_signature_desc.pParameters = &root_parameter;
|
||||||
|
root_signature_desc.Flags = flags;
|
||||||
|
hr = create_root_signature(device, &root_signature_desc, &root_signature);
|
||||||
|
ok_(line)(SUCCEEDED(hr), "Failed to create root signature, hr %#x.\n", hr);
|
||||||
|
|
||||||
|
return root_signature;
|
||||||
|
}
|
||||||
|
|
||||||
static void init_pipeline_state_desc(D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc,
|
static void init_pipeline_state_desc(D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc,
|
||||||
ID3D12RootSignature *root_signature, DXGI_FORMAT rt_format,
|
ID3D12RootSignature *root_signature, DXGI_FORMAT rt_format,
|
||||||
const D3D12_SHADER_BYTECODE *vs, const D3D12_SHADER_BYTECODE *ps,
|
const D3D12_SHADER_BYTECODE *vs, const D3D12_SHADER_BYTECODE *ps,
|
||||||
|
300
tests/shader_runner_d3d12.c
Normal file
300
tests/shader_runner_d3d12.c
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 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 <errno.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct shader_context
|
||||||
|
{
|
||||||
|
struct test_context c;
|
||||||
|
|
||||||
|
ID3D10Blob *ps_code;
|
||||||
|
|
||||||
|
uint32_t *uniforms;
|
||||||
|
size_t uniform_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum parse_state
|
||||||
|
{
|
||||||
|
STATE_NONE,
|
||||||
|
STATE_SHADER_PIXEL,
|
||||||
|
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_test_directive(struct shader_context *context, const char *line)
|
||||||
|
{
|
||||||
|
const char *const orig_line = 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;
|
||||||
|
static const float clear_color[4];
|
||||||
|
ID3D12PipelineState *pso;
|
||||||
|
|
||||||
|
context->c.root_signature = create_32bit_constants_root_signature(context->c.device,
|
||||||
|
0, context->uniform_count, D3D12_SHADER_VISIBILITY_ALL);
|
||||||
|
|
||||||
|
pso = create_pipeline_state(context->c.device, context->c.root_signature,
|
||||||
|
context->c.render_target_desc.Format, NULL, &ps, NULL);
|
||||||
|
|
||||||
|
ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, context->c.root_signature);
|
||||||
|
ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(command_list, 0,
|
||||||
|
context->uniform_count, context->uniforms, 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);
|
||||||
|
ID3D12PipelineState_Release(pso);
|
||||||
|
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)
|
||||||
|
goto err;
|
||||||
|
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, "uniform", &line))
|
||||||
|
{
|
||||||
|
unsigned int offset;
|
||||||
|
|
||||||
|
if (!sscanf(line, "%u", &offset))
|
||||||
|
goto err;
|
||||||
|
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)
|
||||||
|
goto err;
|
||||||
|
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
|
||||||
|
{
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
err:
|
||||||
|
fprintf(stderr, "Ignoring malformed line '%s'.\n", orig_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(shader_runner_d3d12)
|
||||||
|
{
|
||||||
|
static const struct test_context_desc desc =
|
||||||
|
{
|
||||||
|
.no_root_signature = true,
|
||||||
|
.rt_format = DXGI_FORMAT_R32G32B32A32_FLOAT,
|
||||||
|
};
|
||||||
|
size_t shader_source_size = 0, shader_source_len = 0;
|
||||||
|
enum parse_state state = STATE_NONE;
|
||||||
|
struct shader_context context;
|
||||||
|
const char *filename = NULL;
|
||||||
|
char *shader_source = NULL;
|
||||||
|
unsigned int i;
|
||||||
|
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")))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Unable to open '%s' for reading: %s\n", argv[1], strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&context, 0, sizeof(context));
|
||||||
|
init_test_context(&context.c, &desc);
|
||||||
|
|
||||||
|
while (fgets(line, sizeof(line), f))
|
||||||
|
{
|
||||||
|
if (line[0] == '[')
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case STATE_NONE:
|
||||||
|
case STATE_TEST:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_SHADER_PIXEL:
|
||||||
|
if (!(context.ps_code = compile_shader(shader_source, "ps_4_0")))
|
||||||
|
return;
|
||||||
|
shader_source_len = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(line, "[pixel shader]\n"))
|
||||||
|
state = STATE_SHADER_PIXEL;
|
||||||
|
else if (!strcmp(line, "[test]\n"))
|
||||||
|
state = STATE_TEST;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case STATE_NONE:
|
||||||
|
if (line[0] != '#')
|
||||||
|
fprintf(stderr, "Ignoring line '%s' in %s.\n", line, argv[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
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_TEST:
|
||||||
|
if (line[0] != '#')
|
||||||
|
parse_test_directive(&context, line);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ID3D10Blob_Release(context.ps_code);
|
||||||
|
destroy_test_context(&context.c);
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user