Skip to content
Permalink
Browse files

Vulkan: Use Common::DynamicLibrary

  • Loading branch information...
stenzek committed Mar 9, 2019
1 parent a4f7c04 commit f6641b7e4fd666a620843f1a3b5d5117a1397f9c
Showing with 28 additions and 122 deletions.
  1. +28 −122 Source/Core/VideoBackends/Vulkan/VulkanLoader.cpp
@@ -7,18 +7,13 @@
#include <cstdlib>

#include "Common/CommonFuncs.h"
#include "Common/DynamicLibrary.h"
#include "Common/FileUtil.h"
#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"

#include "VideoBackends/Vulkan/VulkanLoader.h"

#if defined(_WIN32)
#include <Windows.h>
#else
#include <dlfcn.h>
#endif

#define VULKAN_MODULE_ENTRY_POINT(name, required) PFN_##name name;
#define VULKAN_INSTANCE_ENTRY_POINT(name, required) PFN_##name name;
#define VULKAN_DEVICE_ENTRY_POINT(name, required) PFN_##name name;
@@ -40,145 +35,56 @@ static void ResetVulkanLibraryFunctionPointers()
#undef VULKAN_MODULE_ENTRY_POINT
}

#if defined(_WIN32)

static HMODULE vulkan_module;
static std::atomic_int vulkan_module_ref_count = {0};

bool LoadVulkanLibrary()
{
// Not thread safe if a second thread calls the loader whilst the first is still in-progress.
if (vulkan_module)
{
vulkan_module_ref_count++;
return true;
}

vulkan_module = LoadLibraryA("vulkan-1.dll");
if (!vulkan_module)
{
ERROR_LOG(VIDEO, "Failed to load vulkan-1.dll");
return false;
}

bool required_functions_missing = false;
auto LoadFunction = [&](FARPROC* func_ptr, const char* name, bool is_required) {
*func_ptr = GetProcAddress(vulkan_module, name);
if (!(*func_ptr) && is_required)
{
ERROR_LOG(VIDEO, "Vulkan: Failed to load required module function %s", name);
required_functions_missing = true;
}
};

#define VULKAN_MODULE_ENTRY_POINT(name, required) \
LoadFunction(reinterpret_cast<FARPROC*>(&name), #name, required);
#include "VideoBackends/Vulkan/VulkanEntryPoints.inl"
#undef VULKAN_MODULE_ENTRY_POINT

if (required_functions_missing)
{
ResetVulkanLibraryFunctionPointers();
FreeLibrary(vulkan_module);
vulkan_module = nullptr;
return false;
}

vulkan_module_ref_count++;
return true;
}

void UnloadVulkanLibrary()
{
if ((--vulkan_module_ref_count) > 0)
return;

ResetVulkanLibraryFunctionPointers();
FreeLibrary(vulkan_module);
vulkan_module = nullptr;
}

#else

static void* vulkan_module;
static std::atomic_int vulkan_module_ref_count = {0};
static Common::DynamicLibrary s_vulkan_module;

bool LoadVulkanLibrary()
static std::string GetVulkanLibraryFilename()
{
// Not thread safe if a second thread calls the loader whilst the first is still in-progress.
if (vulkan_module)
{
vulkan_module_ref_count++;
return true;
}

#if defined(__APPLE__)
#ifdef __APPLE__
// Check if a path to a specific Vulkan library has been specified.
char* libvulkan_env = getenv("LIBVULKAN_PATH");
if (libvulkan_env)
vulkan_module = dlopen(libvulkan_env, RTLD_NOW);
if (!vulkan_module)
{
// Use the libvulkan.dylib from the application bundle.
std::string path = File::GetBundleDirectory() + "/Contents/Frameworks/libvulkan.dylib";
vulkan_module = dlopen(path.c_str(), RTLD_NOW);
}
return std::string(libvulkan_env);

// Use the libvulkan.dylib from the application bundle.
return File::GetBundleDirectory() + "/Contents/Frameworks/libvulkan.dylib";
#else
// Names of libraries to search. Desktop should use libvulkan.so.1 or libvulkan.so.
static const char* search_lib_names[] = {"libvulkan.so.1", "libvulkan.so"};
for (size_t i = 0; i < ArraySize(search_lib_names); i++)
{
vulkan_module = dlopen(search_lib_names[i], RTLD_NOW);
if (vulkan_module)
break;
}
return Common::DynamicLibrary::GetVersionedFilename("vulkan", 1);
#endif
}

if (!vulkan_module)
bool LoadVulkanLibrary()
{
if (!s_vulkan_module.IsOpen())
{
ERROR_LOG(VIDEO, "Failed to load or locate libvulkan.so");
return false;
}

bool required_functions_missing = false;
auto LoadFunction = [&](void** func_ptr, const char* name, bool is_required) {
*func_ptr = dlsym(vulkan_module, name);
if (!(*func_ptr) && is_required)
const std::string filename = GetVulkanLibraryFilename();
if (!s_vulkan_module.Open(filename.c_str()))
{
ERROR_LOG(VIDEO, "Vulkan: Failed to load required module function %s", name);
required_functions_missing = true;
ERROR_LOG(VIDEO, "Failed to load %s", filename.c_str());
return false;
}
};
}

#define VULKAN_MODULE_ENTRY_POINT(name, required) \
LoadFunction(reinterpret_cast<void**>(&name), #name, required);
if (!s_vulkan_module.GetSymbol(#name, &name) && required) \
{ \
ERROR_LOG(VIDEO, "Vulkan: Failed to load required module function %s", #name); \
ResetVulkanLibraryFunctionPointers(); \
s_vulkan_module.Close(); \
return false; \
}
#include "VideoBackends/Vulkan/VulkanEntryPoints.inl"
#undef VULKAN_MODULE_ENTRY_POINT

if (required_functions_missing)
{
ResetVulkanLibraryFunctionPointers();
dlclose(vulkan_module);
vulkan_module = nullptr;
return false;
}

vulkan_module_ref_count++;
return true;
}

void UnloadVulkanLibrary()
{
if ((--vulkan_module_ref_count) > 0)
return;

ResetVulkanLibraryFunctionPointers();
dlclose(vulkan_module);
vulkan_module = nullptr;
s_vulkan_module.Close();
if (!s_vulkan_module.IsOpen())
ResetVulkanLibraryFunctionPointers();
}

#endif

bool LoadVulkanInstanceFunctions(VkInstance instance)
{
bool required_functions_missing = false;

0 comments on commit f6641b7

Please sign in to comment.
You can’t perform that action at this time.