[vulkan] Make LibraryLoader dynamically load vulkan-1

This makes LibraryLoader actually load the library and moves ownership
of GetInstanceProcAddr into it, which means we pass through the
loaders into their parents to grab stuff.
This commit is contained in:
Joshua Ashton 2022-08-26 17:33:25 +00:00 committed by Philip Rebohle
parent f6fcbb7127
commit 482a7e433b
6 changed files with 48 additions and 26 deletions

View File

@ -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')

View File

@ -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);
}

View File

@ -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();

View File

@ -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 ],
)

View File

@ -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<PFN_vkGetInstanceProcAddr>(
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<LibraryLoader>& 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<PFN_vkGetDeviceProcAddr>(
dxvk::vk::GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"))),
DeviceLoader::DeviceLoader(const Rc<InstanceLoader>& library, bool owned, VkDevice device)
: m_library(library)
, m_getDeviceProcAddr(reinterpret_cast<PFN_vkGetDeviceProcAddr>(
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<LibraryLoader>& 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<InstanceLoader>& library, bool owned, VkDevice device)
: DeviceLoader(library, owned, device) { }
DeviceFn::~DeviceFn() {
if (m_owned)
this->vkDestroyDevice(m_device, nullptr);

View File

@ -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<LibraryLoader>& 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<LibraryLoader> 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<InstanceLoader>& library, bool owned, VkDevice device);
PFN_vkVoidFunction sym(const char* name) const;
VkDevice device() const { return m_device; }
protected:
Rc<InstanceLoader> 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<LibraryLoader>& 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<InstanceLoader>& library, bool owned, VkDevice device);
~DeviceFn();
VULKAN_FN(vkDestroyDevice);