diff --git a/meson.build b/meson.build index e8b15fa96..b24c3a920 100644 --- a/meson.build +++ b/meson.build @@ -69,7 +69,6 @@ if platform == 'windows' dxvk_library_path = meson.current_source_dir() + '/lib32' endif - lib_vulkan = cpp.find_library('vulkan-1', dirs : dxvk_library_path) lib_d3d9 = cpp.find_library('d3d9') lib_d3d11 = cpp.find_library('d3d11') lib_dxgi = cpp.find_library('dxgi') @@ -100,7 +99,6 @@ if platform == 'windows' dxvk_wsi = 'win32' compiler_args += ['-DDXVK_WSI_WIN32'] else - lib_vulkan = cpp.find_library('vulkan') lib_sdl2 = cpp.find_library('SDL2') wrc = find_program('touch') diff --git a/src/dxvk/dxvk_adapter.cpp b/src/dxvk/dxvk_adapter.cpp index 4479686fa..09d2c7994 100644 --- a/src/dxvk/dxvk_adapter.cpp +++ b/src/dxvk/dxvk_adapter.cpp @@ -523,7 +523,7 @@ namespace dxvk { throw DxvkError("DxvkAdapter: Failed to create device"); return new DxvkDevice(instance, this, - new vk::DeviceFn(true, m_vki->instance(), device), + new vk::DeviceFn(m_vki, true, device), devExtensions, enabledFeatures); } diff --git a/src/dxvk/dxvk_instance.cpp b/src/dxvk/dxvk_instance.cpp index 5efa4cf82..0d8d5a075 100644 --- a/src/dxvk/dxvk_instance.cpp +++ b/src/dxvk/dxvk_instance.cpp @@ -33,7 +33,7 @@ namespace dxvk { provider->initInstanceExtensions(); m_vkl = new vk::LibraryFn(); - m_vki = new vk::InstanceFn(true, this->createInstance()); + m_vki = new vk::InstanceFn(m_vkl, true, this->createInstance()); m_adapters = this->queryAdapters(); diff --git a/src/vulkan/meson.build b/src/vulkan/meson.build index 91350ea10..7fa26c18d 100644 --- a/src/vulkan/meson.build +++ b/src/vulkan/meson.build @@ -7,7 +7,7 @@ vkcommon_src = files([ thread_dep = dependency('threads') vkcommon_lib = static_library('vkcommon', vkcommon_src, - dependencies : [ thread_dep, lib_vulkan ], + dependencies : [ thread_dep ], include_directories : [ dxvk_include_path ], ) diff --git a/src/vulkan/vulkan_loader.cpp b/src/vulkan/vulkan_loader.cpp index faa5155f9..49ed5cf28 100644 --- a/src/vulkan/vulkan_loader.cpp +++ b/src/vulkan/vulkan_loader.cpp @@ -1,26 +1,41 @@ #include "vulkan_loader.h" +#include "../util/util_win32_compat.h" + namespace dxvk::vk { - static const PFN_vkGetInstanceProcAddr GetInstanceProcAddr = vkGetInstanceProcAddr; + LibraryLoader::LibraryLoader() + : m_library(LoadLibraryA("vulkan-1")) + , m_getInstanceProcAddr(reinterpret_cast( + GetProcAddress(m_library, "vkGetInstanceProcAddr"))) { + } + + LibraryLoader::~LibraryLoader() { + FreeLibrary(m_library); + } + + PFN_vkVoidFunction LibraryLoader::sym(VkInstance instance, const char* name) const { + return m_getInstanceProcAddr(instance, name); + } PFN_vkVoidFunction LibraryLoader::sym(const char* name) const { - return dxvk::vk::GetInstanceProcAddr(nullptr, name); + return sym(nullptr, name); } - InstanceLoader::InstanceLoader(bool owned, VkInstance instance) - : m_instance(instance), m_owned(owned) { } + InstanceLoader::InstanceLoader(const Rc& library, bool owned, VkInstance instance) + : m_library(library), m_instance(instance), m_owned(owned) { } PFN_vkVoidFunction InstanceLoader::sym(const char* name) const { - return dxvk::vk::GetInstanceProcAddr(m_instance, name); + return m_library->sym(m_instance, name); } - DeviceLoader::DeviceLoader(bool owned, VkInstance instance, VkDevice device) - : m_getDeviceProcAddr(reinterpret_cast( - dxvk::vk::GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"))), + DeviceLoader::DeviceLoader(const Rc& library, bool owned, VkDevice device) + : m_library(library) + , m_getDeviceProcAddr(reinterpret_cast( + m_library->sym("vkGetDeviceProcAddr"))), m_device(device), m_owned(owned) { } @@ -33,16 +48,16 @@ namespace dxvk::vk { LibraryFn::~LibraryFn() { } - InstanceFn::InstanceFn(bool owned, VkInstance instance) - : InstanceLoader(owned, instance) { } + InstanceFn::InstanceFn(const Rc& library, bool owned, VkInstance instance) + : InstanceLoader(library, owned, instance) { } InstanceFn::~InstanceFn() { if (m_owned) this->vkDestroyInstance(m_instance, nullptr); } - DeviceFn::DeviceFn(bool owned, VkInstance instance, VkDevice device) - : DeviceLoader(owned, instance, device) { } + DeviceFn::DeviceFn(const Rc& library, bool owned, VkDevice device) + : DeviceLoader(library, owned, device) { } DeviceFn::~DeviceFn() { if (m_owned) this->vkDestroyDevice(m_device, nullptr); diff --git a/src/vulkan/vulkan_loader.h b/src/vulkan/vulkan_loader.h index 6f469c650..ff56cb01c 100644 --- a/src/vulkan/vulkan_loader.h +++ b/src/vulkan/vulkan_loader.h @@ -10,15 +10,22 @@ ::PFN_ ## name name = reinterpret_cast<::PFN_ ## name>(sym(#name)) namespace dxvk::vk { - + /** * \brief Vulkan library loader * - * Provides methods to load Vulkan functions that - * can be called before creating a instance. + * Dynamically loads the vulkan-1 library and + * provides methods to load Vulkan functions that + * can be called before creating a instance. */ struct LibraryLoader : public RcObject { + LibraryLoader(); + ~LibraryLoader(); + PFN_vkVoidFunction sym(VkInstance instance, const char* name) const; PFN_vkVoidFunction sym(const char* name) const; + protected: + const HMODULE m_library; + const PFN_vkGetInstanceProcAddr m_getInstanceProcAddr; }; @@ -29,12 +36,13 @@ namespace dxvk::vk { * called for a specific instance. */ struct InstanceLoader : public RcObject { - InstanceLoader(bool owned, VkInstance instance); + InstanceLoader(const Rc& library, bool owned, VkInstance instance); PFN_vkVoidFunction sym(const char* name) const; VkInstance instance() const { return m_instance; } protected: - const VkInstance m_instance; - const bool m_owned; + Rc m_library; + const VkInstance m_instance; + const bool m_owned; }; @@ -45,10 +53,11 @@ namespace dxvk::vk { * specific device. */ struct DeviceLoader : public RcObject { - DeviceLoader(bool owned, VkInstance instance, VkDevice device); + DeviceLoader(const Rc& library, bool owned, VkDevice device); PFN_vkVoidFunction sym(const char* name) const; VkDevice device() const { return m_device; } protected: + Rc m_library; const PFN_vkGetDeviceProcAddr m_getDeviceProcAddr; const VkDevice m_device; const bool m_owned; @@ -78,7 +87,7 @@ namespace dxvk::vk { * are independent of any Vulkan devices. */ struct InstanceFn : InstanceLoader { - InstanceFn(bool owned, VkInstance instance); + InstanceFn(const Rc& library, bool owned, VkInstance instance); ~InstanceFn(); VULKAN_FN(vkCreateDevice); @@ -160,7 +169,7 @@ namespace dxvk::vk { * This ensures that no slow dispatch code is executed. */ struct DeviceFn : DeviceLoader { - DeviceFn(bool owned, VkInstance instance, VkDevice device); + DeviceFn(const Rc& library, bool owned, VkDevice device); ~DeviceFn(); VULKAN_FN(vkDestroyDevice);