diff --git a/Makefile.am b/Makefile.am index a790243a..b08e50ce 100644 --- a/Makefile.am +++ b/Makefile.am @@ -457,15 +457,20 @@ LDADD = libvkd3d.la libvkd3d-shader.la libvkd3d-utils.la AM_DEFAULT_SOURCE_EXT = .c TEST_EXTENSIONS = .shader_test +TEST_CPPFLAGS = -I$(builddir)/tests if BUILD_TESTS check_PROGRAMS = $(vkd3d_tests) $(vkd3d_cross_tests) tests/shader_runner dist_check_SCRIPTS = tests/test-driver.sh TESTS = $(vkd3d_tests) $(vkd3d_cross_tests) $(vkd3d_shader_tests) +tests_d3d12_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS) tests_d3d12_LDADD = $(LDADD) @PTHREAD_LIBS@ @DL_LIBS@ +tests_d3d12_invalid_usage_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS) tests_d3d12_invalid_usage_LDADD = $(LDADD) @DL_LIBS@ +tests_hlsl_d3d12_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS) tests_hlsl_d3d12_LDADD = $(LDADD) @DL_LIBS@ -tests_shader_runner_CFLAGS = $(AM_CFLAGS) -I$(builddir)/tests @OPENGL_CFLAGS@ +tests_shader_runner_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS) +tests_shader_runner_CFLAGS = $(AM_CFLAGS) @OPENGL_CFLAGS@ tests_shader_runner_LDADD = $(LDADD) @OPENGL_LIBS@ @DL_LIBS@ tests_shader_runner_SOURCES = \ tests/shader_runner.c \ @@ -474,7 +479,9 @@ tests_shader_runner_SOURCES = \ tests/shader_runner_d3d12.c \ tests/shader_runner_gl.c \ tests/shader_runner_vulkan.c +tests_vkd3d_api_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS) tests_vkd3d_api_LDADD = libvkd3d.la @DL_LIBS@ +tests_vkd3d_shader_api_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS) tests_vkd3d_shader_api_CFLAGS = $(AM_CFLAGS) @OPENGL_CFLAGS@ tests_vkd3d_shader_api_LDADD = libvkd3d-shader.la @OPENGL_LIBS@ SHADER_TEST_LOG_COMPILER = tests/shader_runner diff --git a/tests/shader_runner.c b/tests/shader_runner.c index 692ff90a..cf881b6a 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -62,7 +62,6 @@ typedef int HRESULT; #include "vkd3d_d3dcompiler.h" #include "vkd3d_test.h" #include "shader_runner.h" -#include "dxcompiler.h" struct test_options test_options = {0}; @@ -1391,55 +1390,28 @@ const char *shader_type_string(enum shader_type type) return shader_types[type]; } -/* Avoid issues with calling convention mismatch and different methods for string - * retrieval by copying all IDxcBlob objects to a new ID3D10Blob. */ - -static void d3d10_blob_from_dxc_blob_utf8(IDxcBlobUtf8 *blob, ID3D10Blob **blob_out) +static HRESULT d3d10_blob_from_vkd3d_shader_code(const struct vkd3d_shader_code *blob, ID3D10Blob **blob_out) { ID3D10Blob *d3d_blob; - size_t size; HRESULT hr; - size = IDxcBlobUtf8_GetStringLength(blob) + 1; - if (FAILED(hr = D3DCreateBlob(size, (ID3DBlob **)&d3d_blob))) - { - trace("Failed to create blob, hr %#x.\n", hr); - return; - } - - memcpy(ID3D10Blob_GetBufferPointer(d3d_blob), IDxcBlobUtf8_GetStringPointer(blob), size); - *blob_out = d3d_blob; -} - -static HRESULT d3d10_blob_from_dxc_blob(IDxcBlob *blob, ID3D10Blob **blob_out) -{ - ID3D10Blob *d3d_blob; - size_t size; - HRESULT hr; - - size = IDxcBlob_GetBufferSize(blob); - if (FAILED(hr = D3DCreateBlob(size, (ID3DBlob **)&d3d_blob))) + if (FAILED(hr = D3DCreateBlob(blob->size, (ID3DBlob **)&d3d_blob))) { trace("Failed to create blob, hr %#x.\n", hr); return hr; } - memcpy(ID3D10Blob_GetBufferPointer(d3d_blob), IDxcBlob_GetBufferPointer(blob), size); + memcpy(ID3D10Blob_GetBufferPointer(d3d_blob), blob->code, blob->size); *blob_out = d3d_blob; return S_OK; } -HRESULT dxc_compiler_compile_shader(void *dxc_compiler, enum shader_type type, unsigned int compile_options, - const char *hlsl, ID3D10Blob **blob_out, ID3D10Blob **errors_out) +HRESULT dxc_compiler_compile_shader(void *dxc_compiler, enum shader_type type, + unsigned int compile_options, const char *hlsl, ID3D10Blob **blob_out) { - DxcBuffer src_buf = {hlsl, strlen(hlsl), 65001}; - IDxcCompiler3 *compiler = dxc_compiler; - HRESULT hr, compile_hr; - IDxcBlobUtf8 *errors; - IDxcResult *result; - size_t arg_count; - IDxcBlob *blob; + struct vkd3d_shader_code blob; + HRESULT hr; static const WCHAR *const shader_profiles[] = { @@ -1450,62 +1422,15 @@ HRESULT dxc_compiler_compile_shader(void *dxc_compiler, enum shader_type type, u [SHADER_TYPE_DS] = L"ds_6_0", [SHADER_TYPE_GS] = L"gs_6_0", }; - const WCHAR *args[] = - { - L"/T", - shader_profiles[type], - L"/Qstrip_reflect", - L"/Qstrip_debug", - L"/flegacy-macro-expansion", - L"/flegacy-resource-reservation", - NULL, - NULL, - NULL, - }; *blob_out = NULL; - *errors_out = NULL; - arg_count = ARRAY_SIZE(args) - 3; - if (compile_options & D3DCOMPILE_PACK_MATRIX_ROW_MAJOR) - args[arg_count++] = L"/Zpr"; - if (compile_options & D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR) - args[arg_count++] = L"/Zpc"; - if (compile_options & D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY) - args[arg_count++] = L"/Gec"; - - if (FAILED(hr = IDxcCompiler3_Compile(compiler, &src_buf, args, arg_count, NULL, &IID_IDxcResult, (void **)&result))) - { - trace("Failed to compile shader, hr %#x.\n", hr); + if (FAILED(hr = dxc_compile(dxc_compiler, shader_profiles[type], compile_options, hlsl, &blob))) return hr; - } - if (IDxcResult_HasOutput(result, DXC_OUT_ERRORS) - && SUCCEEDED(hr = IDxcResult_GetOutput(result, DXC_OUT_ERRORS, &IID_IDxcBlobUtf8, (void **)&errors, NULL))) - { - if (IDxcBlobUtf8_GetStringLength(errors)) - d3d10_blob_from_dxc_blob_utf8(errors, errors_out); - IDxcBlobUtf8_Release(errors); - } + hr = d3d10_blob_from_vkd3d_shader_code(&blob, blob_out); + free((void *)blob.code); - if (FAILED(hr = IDxcResult_GetStatus(result, &compile_hr)) || FAILED((hr = compile_hr))) - { - if (hr == DXC_E_LLVM_CAST_ERROR) - hr = E_FAIL; - goto result_release; - } - - if (FAILED(hr = IDxcResult_GetOutput(result, DXC_OUT_OBJECT, &IID_IDxcBlob, (void **)&blob, NULL))) - goto result_release; - - IDxcResult_Release(result); - - hr = d3d10_blob_from_dxc_blob(blob, blob_out); - IDxcBlob_Release(blob); - return hr; - -result_release: - IDxcResult_Release(result); return hr; } @@ -1539,7 +1464,7 @@ static void compile_shader(struct shader_runner *runner, IDxcCompiler3 *dxc_comp if (use_dxcompiler) { assert(dxc_compiler); - hr = dxc_compiler_compile_shader(dxc_compiler, type, runner->compile_options, source, &blob, &errors); + hr = dxc_compiler_compile_shader(dxc_compiler, type, runner->compile_options, source, &blob); } else { @@ -1558,7 +1483,8 @@ static void compile_shader(struct shader_runner *runner, IDxcCompiler3 *dxc_comp else { assert_that(!blob, "Expected no compiled shader blob.\n"); - assert_that(!!errors, "Expected non-NULL error blob.\n"); + if (!use_dxcompiler) + assert_that(!!errors, "Expected non-NULL error blob.\n"); } if (errors) { @@ -2299,46 +2225,6 @@ out: } #endif -#if (defined(SONAME_LIBDXCOMPILER) || defined(VKD3D_CROSSTEST)) -static IDxcCompiler3 *dxcompiler_create(void) -{ - DxcCreateInstanceProc create_instance; - IDxcCompiler3 *compiler; - const char *skip_dxc; - HRESULT hr; - void *dll; - - if ((skip_dxc = getenv("VKD3D_TEST_SKIP_DXC")) && strcmp(skip_dxc, "") != 0) - return NULL; - -#ifdef VKD3D_CROSSTEST - dll = vkd3d_dlopen("dxcompiler.dll"); -#else - dll = vkd3d_dlopen(SONAME_LIBDXCOMPILER); -#endif - ok(dll, "Failed to load dxcompiler library, %s.\n", vkd3d_dlerror()); - if (!dll) - return NULL; - - create_instance = (DxcCreateInstanceProc)vkd3d_dlsym(dll, "DxcCreateInstance"); - ok(create_instance, "Failed to get DxcCreateInstance() pointer.\n"); - if (!create_instance) - return NULL; - - hr = create_instance(&CLSID_DxcCompiler, &IID_IDxcCompiler3, (void **)&compiler); - ok(SUCCEEDED(hr), "Failed to create instance, hr %#x.\n", hr); - if (FAILED(hr)) - return NULL; - - return compiler; -} -#else -static IDxcCompiler3 *dxcompiler_create(void) -{ - return NULL; -} -#endif - START_TEST(shader_runner) { IDxcCompiler3 *dxc_compiler; diff --git a/tests/shader_runner.h b/tests/shader_runner.h index a4ae8b95..99078cc6 100644 --- a/tests/shader_runner.h +++ b/tests/shader_runner.h @@ -242,8 +242,8 @@ void fatal_error(const char *format, ...) VKD3D_NORETURN VKD3D_PRINTF_FUNC(1, 2) unsigned int get_vb_stride(const struct shader_runner *runner, unsigned int slot); void init_resource(struct resource *resource, const struct resource_params *params); -HRESULT dxc_compiler_compile_shader(void *dxc_compiler, enum shader_type type, unsigned int compile_options, - const char *hlsl, ID3D10Blob **blob_out, ID3D10Blob **errors_out); +HRESULT dxc_compiler_compile_shader(void *dxc_compiler, enum shader_type type, + unsigned int compile_options, const char *hlsl, ID3D10Blob **blob_out); struct sampler *shader_runner_get_sampler(struct shader_runner *runner, unsigned int slot); struct resource *shader_runner_get_resource(struct shader_runner *runner, enum resource_type type, unsigned int slot); diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index 0d0ef4cf..f16e4c7d 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -85,12 +85,13 @@ static ID3D10Blob *compile_shader(const struct d3d12_shader_runner *runner, cons if (runner->r.minimum_shader_model >= SHADER_MODEL_6_0) { assert(runner->dxc_compiler); - hr = dxc_compiler_compile_shader(runner->dxc_compiler, type, runner->r.compile_options, source, &blob, &errors); + hr = dxc_compiler_compile_shader(runner->dxc_compiler, type, runner->r.compile_options, source, &blob); } else { sprintf(profile, "%s_%s", shader_type_string(type), shader_models[runner->r.minimum_shader_model]); - hr = D3DCompile(source, strlen(source), NULL, NULL, NULL, "main", profile, runner->r.compile_options, 0, &blob, &errors); + hr = D3DCompile(source, strlen(source), NULL, NULL, NULL, "main", + profile, runner->r.compile_options, 0, &blob, &errors); } ok(FAILED(hr) == !blob, "Got unexpected hr %#x, blob %p.\n", hr, blob); if (errors) diff --git a/tests/utils.h b/tests/utils.h index 081c4cd9..ae042a37 100644 --- a/tests/utils.h +++ b/tests/utils.h @@ -44,6 +44,9 @@ #include #include "vkd3d_test.h" #include "vkd3d_d3d12.h" +#include "vkd3d_d3dcompiler.h" +#include "vkd3d_shader.h" +#include "dxcompiler.h" struct vec2 { @@ -453,4 +456,129 @@ static inline void parse_args(int argc, char **argv) } } +static inline HRESULT vkd3d_shader_code_from_dxc_blob(IDxcBlob *blob, struct vkd3d_shader_code *blob_out) +{ + size_t size; + + size = IDxcBlob_GetBufferSize(blob); + if (!(blob_out->code = malloc(size))) + { + trace("Failed to allocate shader code.\n"); + return E_OUTOFMEMORY; + } + + memcpy((void *)blob_out->code, IDxcBlob_GetBufferPointer(blob), size); + blob_out->size = size; + + return S_OK; +} + +static inline HRESULT dxc_compile(void *dxc_compiler, const WCHAR *profile, + unsigned int compile_options, const char *hlsl, struct vkd3d_shader_code *blob_out) +{ + DxcBuffer src_buf = {hlsl, strlen(hlsl), 65001}; + IDxcCompiler3 *compiler = dxc_compiler; + IDxcBlobUtf8 *errors; + IDxcResult *result; + HRESULT compile_hr; + size_t arg_count; + IDxcBlob *blob; + int hr; + + const WCHAR *args[] = + { + L"/T", + profile, + L"/Qstrip_reflect", + L"/Qstrip_debug", + L"/flegacy-macro-expansion", + L"/flegacy-resource-reservation", + NULL, + NULL, + NULL, + }; + + memset(blob_out, 0, sizeof(*blob_out)); + + arg_count = ARRAY_SIZE(args) - 3; + if (compile_options & D3DCOMPILE_PACK_MATRIX_ROW_MAJOR) + args[arg_count++] = L"/Zpr"; + if (compile_options & D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR) + args[arg_count++] = L"/Zpc"; + if (compile_options & D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY) + args[arg_count++] = L"/Gec"; + + if (FAILED(hr = IDxcCompiler3_Compile(compiler, &src_buf, args, + arg_count, NULL, &IID_IDxcResult, (void **)&result))) + return hr; + + if (IDxcResult_HasOutput(result, DXC_OUT_ERRORS) + && SUCCEEDED(hr = IDxcResult_GetOutput(result, DXC_OUT_ERRORS, &IID_IDxcBlobUtf8, (void **)&errors, NULL))) + { + if (IDxcBlobUtf8_GetStringLength(errors) && vkd3d_test_state.debug_level) + trace("%s\n", (char *)IDxcBlobUtf8_GetStringPointer(errors)); + IDxcBlobUtf8_Release(errors); + } + + if (FAILED(hr = IDxcResult_GetStatus(result, &compile_hr)) || FAILED((hr = compile_hr))) + { + if (hr == DXC_E_LLVM_CAST_ERROR) + hr = E_FAIL; + goto result_release; + } + + if (FAILED(hr = IDxcResult_GetOutput(result, DXC_OUT_OBJECT, &IID_IDxcBlob, (void **)&blob, NULL))) + goto result_release; + + IDxcResult_Release(result); + + hr = vkd3d_shader_code_from_dxc_blob(blob, blob_out); + IDxcBlob_Release(blob); + return hr; + +result_release: + IDxcResult_Release(result); + return hr; +} + +#if (defined(SONAME_LIBDXCOMPILER) || defined(VKD3D_CROSSTEST)) +static inline IDxcCompiler3 *dxcompiler_create(void) +{ + DxcCreateInstanceProc create_instance; + IDxcCompiler3 *compiler; + const char *skip_dxc; + void *dll; + int hr; + + if ((skip_dxc = getenv("VKD3D_TEST_SKIP_DXC")) && strcmp(skip_dxc, "") != 0) + return NULL; + +# ifdef VKD3D_CROSSTEST + dll = vkd3d_dlopen("dxcompiler.dll"); +# else + dll = vkd3d_dlopen(SONAME_LIBDXCOMPILER); +# endif + ok(dll, "Failed to load dxcompiler library, %s.\n", vkd3d_dlerror()); + if (!dll) + return NULL; + + create_instance = (DxcCreateInstanceProc)vkd3d_dlsym(dll, "DxcCreateInstance"); + ok(create_instance, "Failed to get DxcCreateInstance() pointer.\n"); + if (!create_instance) + return NULL; + + hr = create_instance(&CLSID_DxcCompiler, &IID_IDxcCompiler3, (void **)&compiler); + ok(SUCCEEDED(hr), "Failed to create instance, hr %#x.\n", hr); + if (FAILED(hr)) + return NULL; + + return compiler; +} +#else +static inline IDxcCompiler3 *dxcompiler_create(void) +{ + return NULL; +} +#endif + #endif