diff --git a/libs/vkd3d-common/guid.c b/libs/vkd3d-common/guid.c new file mode 100644 index 0000000000..e89da89b82 --- /dev/null +++ b/libs/vkd3d-common/guid.c @@ -0,0 +1,24 @@ +/* + * Copyright 2024 Hans-Kristian Arntzen for Valve Corporation + * + * 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 + */ + +/* Need a common place to define these GUIDs, otherwise we have a mess with + * either double definitions or missing definitions in the programs/. */ +#ifdef VKD3D_ENABLE_DXILCONV +#define INITGUID +#include "vkd3d_dxcapi.h" +#endif diff --git a/libs/vkd3d-common/meson.build b/libs/vkd3d-common/meson.build index c3c22abf60..650ceaa3c2 100644 --- a/libs/vkd3d-common/meson.build +++ b/libs/vkd3d-common/meson.build @@ -6,6 +6,7 @@ vkd3d_common_src = [ 'string.c', 'file_utils.c', 'platform.c', + 'guid.c', ] vkd3d_common_lib = static_library('vkd3d_common', vkd3d_common_src, vkd3d_header_files, diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index bd301a2a54..88c11dc697 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -22,10 +22,13 @@ #include "vkd3d_string.h" #include "vkd3d_platform.h" +#include "vkd3d_threads.h" #include #include +#include "vkd3d_dxcapi.h" + static void vkd3d_shader_dump_blob(const char *path, vkd3d_shader_hash_t hash, const void *data, size_t size, const char *ext) { char filename[1024]; @@ -362,6 +365,37 @@ static int vkd3d_shader_validate_shader_type(enum vkd3d_shader_type type, VkShad return 0; } +#ifdef VKD3D_ENABLE_DXILCONV +static DxcCreateInstanceProc vkd3d_dxilconv_instance_proc; + +static void dxilconv_init_once(void) +{ + vkd3d_module_t module = vkd3d_dlopen("dxilconv.dll"); + if (module) + vkd3d_dxilconv_instance_proc = vkd3d_dlsym(module, "DxcCreateInstance"); + + if (vkd3d_dxilconv_instance_proc) + INFO("Found dxilconv.dll. Will use that for DXBC.\n"); + else + INFO("Did not find dxilconv.dll. Using built-in DXBC implementation.\n"); +} + +static IDxbcConverter *vkd3d_shader_compiler_create_dxbc_converter(void) +{ + static pthread_once_t once_key = PTHREAD_ONCE_INIT; + IDxbcConverter *iface; + + pthread_once(&once_key, dxilconv_init_once); + if (!vkd3d_dxilconv_instance_proc) + return NULL; + + if (FAILED(vkd3d_dxilconv_instance_proc(&CLSID_DxbcConverter, &IID_IDxbcConverter, (void **)&iface))) + return NULL; + + return iface; +} +#endif + int vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_code *spirv, struct vkd3d_shader_code_debug *spirv_debug, @@ -374,6 +408,7 @@ int vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_scan_info scan_info; struct vkd3d_shader_parser parser; vkd3d_shader_hash_t hash; + bool is_dxil; int ret; TRACE("dxbc {%p, %zu}, spirv %p, compiler_options %#x, shader_interface_info %p, compile_args %p.\n", @@ -382,8 +417,36 @@ int vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc, if ((ret = vkd3d_shader_validate_compile_args(compile_args)) < 0) return ret; + is_dxil = shader_is_dxil(dxbc->code, dxbc->size); + +#ifdef VKD3D_ENABLE_DXILCONV + if (!is_dxil) + { + IDxbcConverter *conv = vkd3d_shader_compiler_create_dxbc_converter(); + if (conv) + { + struct vkd3d_shader_code converted; + UINT32 dxil_size; + int ret = -1; + void *dxil; + + if (SUCCEEDED(IDxbcConverter_Convert(conv, dxbc->code, dxbc->size, NULL, &dxil, &dxil_size, NULL))) + { + converted.code = dxil; + converted.size = dxil_size; + ret = vkd3d_shader_compile_dxil(&converted, spirv, spirv_debug, shader_interface_info, compile_args); + CoTaskMemFree(dxil); + } + IDxbcConverter_Release(conv); + + if (ret == 0) + return ret; + } + } +#endif + /* DXIL is handled externally through dxil-spirv. */ - if (shader_is_dxil(dxbc->code, dxbc->size)) + if (is_dxil) { return vkd3d_shader_compile_dxil(dxbc, spirv, spirv_debug, shader_interface_info, compile_args); } diff --git a/meson.build b/meson.build index ee642f2ebd..7b3d27f184 100644 --- a/meson.build +++ b/meson.build @@ -18,6 +18,7 @@ enable_profiling = get_option('enable_profiling') enable_renderdoc = get_option('enable_renderdoc') enable_descriptor_qa = get_option('enable_descriptor_qa') enable_trace = get_option('enable_trace') +enable_dxilconv = get_option('enable_dxilconv') if enable_trace == 'auto' enable_trace = vkd3d_debug @@ -53,6 +54,10 @@ if enable_breadcrumbs add_project_arguments('-DVKD3D_ENABLE_BREADCRUMBS', language : 'c') endif +if enable_dxilconv and vkd3d_platform == 'windows' + add_project_arguments('-DVKD3D_ENABLE_DXILCONV', language : 'c') +endif + vkd3d_external_includes = [ './khronos/Vulkan-Headers/include', './khronos/SPIRV-Headers/include' ] vkd3d_public_includes = [ './include' ] + vkd3d_external_includes vkd3d_private_includes = [ './include/private' ] + vkd3d_public_includes diff --git a/meson_options.txt b/meson_options.txt index ad915ad75a..81936b0326 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -4,3 +4,4 @@ option('enable_profiling', type : 'boolean', value : false) option('enable_renderdoc', type : 'boolean', value : false) option('enable_descriptor_qa', type : 'boolean', value : false) option('enable_trace', type : 'combo', value : 'auto', choices : ['false', 'true', 'auto']) +option('enable_dxilconv', type : 'boolean', value : false)