Skip to content

Commit

Permalink
[vulkan] Make LibraryLoader dynamically load vulkan-1
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
misyltoad authored and doitsujin committed Aug 27, 2022
1 parent f6fcbb7 commit 482a7e4
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 26 deletions.
2 changes: 0 additions & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -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')
Expand Down
2 changes: 1 addition & 1 deletion src/dxvk/dxvk_adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion src/dxvk/dxvk_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
2 changes: 1 addition & 1 deletion src/vulkan/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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 ],
)

Expand Down
39 changes: 27 additions & 12 deletions src/vulkan/vulkan_loader.cpp
Original file line number Diff line number Diff line change
@@ -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) { }


Expand All @@ -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);
Expand Down
27 changes: 18 additions & 9 deletions src/vulkan/vulkan_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};


Expand All @@ -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;
};


Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 482a7e4

Please sign in to comment.