| /* |
| * 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 |