blob: 3927cf206f1c63a701243703cf012d2b03d01db8 [file] [log] [blame]
/*
* Copyright 2025 Rive
*/
#include "logging.hpp"
#include "vulkan_error_handling.hpp"
#include "vulkan_library.hpp"
#include <stdio.h>
#ifndef _WIN32
#include <dlfcn.h>
#endif
namespace rive_vkb
{
std::unique_ptr<VulkanLibrary> VulkanLibrary::Create()
{
// Private constructor, can't use make_unique
bool success = true;
auto outLibrary =
std::unique_ptr<VulkanLibrary>{new VulkanLibrary(&success)};
CONFIRM_OR_RETURN_VALUE(success, nullptr);
return outLibrary;
}
VulkanLibrary::VulkanLibrary(bool* successOut)
{
*successOut = false;
#if !defined(_WIN32) && !defined(__APPLE__) && !defined(__linux__)
static_assert(false, "Unsupported platform");
#endif
constexpr const char* libFilenameCandidates[] = {
#if defined(_WIN32)
"vulkan-1.dll",
#elif defined(__APPLE__)
"libvulkan.dylib",
"libvulkan.1.dylib",
"libMoltenVK.dylib",
// The Vulkan SDK on Mac gets installed to /usr/local/lib, which is no
// longer on the library search path after Sonoma.
"/usr/local/lib/libvulkan.1.dylib",
#else
"libvulkan.so.1",
"libvulkan.so",
#endif
};
for (auto* filenameCandidate : libFilenameCandidates)
{
#ifdef _WIN32
m_library = LoadLibraryA(filenameCandidate);
#else
m_library = dlopen(filenameCandidate, RTLD_NOW | RTLD_LOCAL);
#endif
if (m_library != nullptr)
{
break;
}
}
CONFIRM_OR_RETURN_MSG(m_library != nullptr,
"Failed to find Vulkan library");
#ifdef _WIN32
m_vkGetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
GetProcAddress(m_library, "vkGetInstanceProcAddr"));
#else
m_vkGetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
dlsym(m_library, "vkGetInstanceProcAddr"));
#endif
CONFIRM_OR_RETURN_MSG(
m_vkGetInstanceProcAddr != nullptr,
"Failed to load Vulkan function 'vkGetInstanceProcAddr'");
// This function is allowed to be null
LOAD_MEMBER_INSTANCE_FUNC(this, vkEnumerateInstanceVersion, *this);
LOAD_MEMBER_INSTANCE_FUNC_OR_RETURN(this, vkCreateInstance, *this);
LOAD_MEMBER_INSTANCE_FUNC_OR_RETURN(this,
vkEnumerateInstanceLayerProperties,
*this);
LOAD_MEMBER_INSTANCE_FUNC_OR_RETURN(this,
vkEnumerateInstanceExtensionProperties,
*this);
*successOut = true;
}
VulkanLibrary::~VulkanLibrary()
{
#ifdef _WIN32
if (m_library != nullptr)
{
FreeLibrary(m_library);
}
#else
if (m_library != nullptr)
{
dlclose(m_library);
}
#endif
}
PFN_vkVoidFunction VulkanLibrary::getInstanceProcAddr(VkInstance instance,
const char* name) const
{
return m_vkGetInstanceProcAddr(instance, name);
}
bool VulkanLibrary::canEnumerateInstanceVersion() const
{
return m_vkEnumerateInstanceVersion != nullptr;
}
VkResult VulkanLibrary::enumerateInstanceVersion(uint32_t* outVersion) const
{
return m_vkEnumerateInstanceVersion(outVersion);
}
VkResult VulkanLibrary::createInstance(const VkInstanceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkInstance* pInstance) const
{
return m_vkCreateInstance(pCreateInfo, pAllocator, pInstance);
}
VkResult VulkanLibrary::enumerateInstanceLayerProperties(
uint32_t* pPropertyCount,
VkLayerProperties* pProperties) const
{
return m_vkEnumerateInstanceLayerProperties(pPropertyCount, pProperties);
}
VkResult VulkanLibrary::enumerateInstanceExtensionProperties(
const char* pLayerName,
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties) const
{
return m_vkEnumerateInstanceExtensionProperties(pLayerName,
pPropertyCount,
pProperties);
}
} // namespace rive_vkb