一种简单加载vulkan动态库的方法

前提

最近在国产linux环境上适配vulkan应用,一般系统会自带libvulkan.so.1但是没有libvulkan.so,而libvulkan.so.1无法通过find_library找到,如果系统源没有vulkan sdk或者vulkan loader,这时就得手工下载代码编译vulkan sdk或者vulkan loader,过程中可能还得安装各种依赖,升级cmake,非常繁琐,安装完成后使用下面的方式将vulkan动态库链接到目标应用:

find_package(Vulkan)
if (NOT Vulkan_FOUND)
    find_library(Vulkan_LIBRARIES NAMES vulkan REQUIRED)
endif ()

include_directories(${Vulkan_INCLUDE_DIRS})
target_link_libraries (${PROJECT_NAME} ${Vulkan_LIBRARIES})

在麒麟、龙芯、鲲鹏等各种系统上都经历过手工编译vulkan sdk,为了更快的测试vulkan兼容性以及调试应用,一直在找更简易的方法。

闲暇之余看到了这篇文章 WHAT IS VK_NO_PROTOTYPES,萌生了写一个简易的vulkan动态库加载方法的想法,不用安装vulkan sdk或者vulkan loader,直接使用系统上的libvulkan.so.1(一般都会自带,没有的话执行sudo apt install libvulkan1安装)。

代码示例

基本原理是初始化时使用 dlopen、dlsym加载vulkan动态库中的api函数指针,app直接使用这些api,这里我用了一个开源的动态库加载工具dylib,它支持多系统平台:

GitHub - martin-olivier/dylib: C++ cross-platform wrapper around dynamic loading of shared libraries (dll, so, dylib)

vkCreateInstance函数地址的加载过程为例: 

//加载vulkan动态库
dylib lib("libvulkan.so.1", false);
//定义函数指针vkCreateInstance, PFN_vkCreateInstance的声明在vulkan_core.h中
PFN_vkCreateInstance vkCreateInstance;
//从动态库中获取函数地址
auto vkCreateInstance = (PFN_vkCreateInstance)lib.get_function<PFN_vkCreateInstance>("vkCreateInstance");

这里有个小tip:vkCreateInstance 在vulkan_core.h中的声明是被宏VK_NO_PROTOTYPES括起来的,我们得在cmake中添加该宏定义add_definitions(-DVK_NO_PROTOTYPES),不让 vulkan_core.h中对原生的vk api进行声明,这样我们就可以在load.h中对原生的vulkan api进行声明了。

附上整个load.h的源码,在app初始化时调用vk_loader_init()即可加载vulkan动态库中所有的函数地址:

#include "dylib/dylib.hpp"
#include "vulkan/vulkan_core.h"

#if defined(WIN32) || defined(_WIN32) || defined(_WIN32_) || defined(WIN64) || defined(_WIN64) || defined(_WIN64_)
    #define VULKAN_LIB "vulkan-1.dll"
#elif defined(ANDROID) || defined(_ANDROID_)
    #define VULKAN_LIB "libvulkan.so"
#else
    #define VULKAN_LIB "libvulkan.so.1"
#endif

#define APPLY_PFN_DEF_VK_FUNCTIONS(PFN_DEF)                   \
    PFN_DEF(vkGetInstanceProcAddr)                                 \
    PFN_DEF(vkCreateInstance)                                      \
    PFN_DEF(vkEnumerateInstanceExtensionProperties)                \
    PFN_DEF(vkEnumerateInstanceLayerProperties)                    \
    PFN_DEF(vkDestroyInstance)                                     \
    PFN_DEF(vkEnumeratePhysicalDevices)                            \
    PFN_DEF(vkGetPhysicalDeviceFeatures)                           \
    PFN_DEF(vkGetPhysicalDeviceFormatProperties)                   \
    PFN_DEF(vkGetPhysicalDeviceImageFormatProperties)              \
    PFN_DEF(vkGetPhysicalDeviceProperties)                         \
    PFN_DEF(vkGetPhysicalDeviceQueueFamilyProperties)              \
    PFN_DEF(vkGetPhysicalDeviceMemoryProperties)                   \
    PFN_DEF(vkGetDeviceProcAddr)                                   \
    PFN_DEF(vkCreateDevice)                                        \
    PFN_DEF(vkDestroySurfaceKHR)                                   \
    PFN_DEF(vkGetPhysicalDeviceSurfaceSupportKHR)                  \
    PFN_DEF(vkGetPhysicalDeviceSurfaceCapabilitiesKHR)             \
    PFN_DEF(vkGetPhysicalDeviceSurfaceFormatsKHR)                  \
    PFN_DEF(vkGetPhysicalDeviceSurfacePresentModesKHR)             \
    PFN_DEF(vkCreateSwapchainKHR)                                  \
    PFN_DEF(vkDestroySwapchainKHR)                                 \
    PFN_DEF(vkGetSwapchainImagesKHR)                               \
    PFN_DEF(vkAcquireNextImageKHR)                                 \
    PFN_DEF(vkQueuePresentKHR)                                     \
    PFN_DEF(vkDestroyDevice)                                       \
    PFN_DEF(vkEnumerateDeviceExtensionProperties)                  \
    PFN_DEF(vkEnumerateDeviceLayerProperties)                      \
    PFN_DEF(vkGetDeviceQueue)                                      \
    PFN_DEF(vkQueueSubmit)                                         \
    PFN_DEF(vkQueueWaitIdle)                                       \
    PFN_DEF(vkDeviceWaitIdle)                                      \
    PFN_DEF(vkAllocateMemory)                                      \
    PFN_DEF(vkFreeMemory)                                          \
    PFN_DEF(vkMapMemory)                                           \
    PFN_DEF(vkUnmapMemory)                                         \
    PFN_DEF(vkFlushMappedMemoryRanges)                             \
    PFN_DEF(vkInvalidateMappedMemoryRanges)                        \
    PFN_DEF(vkGetDeviceMemoryCommitment)                           \
    PFN_DEF(vkBindBufferMemory)                                    \
    PFN_DEF(vkBindImageMemory)                                     \
    PFN_DEF(vkGetBufferMemoryRequirements)                         \
    PFN_DEF(vkGetImageMemoryRequirements)                          \
    PFN_DEF(vkGetImageSparseMemoryRequirements)                    \
    PFN_DEF(vkGetPhysicalDeviceSparseImageFormatProperties)        \
    PFN_DEF(vkQueueBindSparse)                                     \
    PFN_DEF(vkCreateFence)                                         \
    PFN_DEF(vkDestroyFence)                                        \
    PFN_DEF(vkResetFences)                                         \
    PFN_DEF(vkGetFenceStatus)                                      \
    PFN_DEF(vkWaitForFences)                                       \
    PFN_DEF(vkCreateSemaphore)                                     \
    PFN_DEF(vkDestroySemaphore)                                    \
    PFN_DEF(vkCreateEvent)                                         \
    PFN_DEF(vkDestroyEvent)                                        \
    PFN_DEF(vkGetEventStatus)                                      \
    PFN_DEF(vkSetEvent)                                            \
    PFN_DEF(vkResetEvent)                                          \
    PFN_DEF(vkCreateQueryPool)                                     \
    PFN_DEF(vkDestroyQueryPool)                                    \
    PFN_DEF(vkGetQueryPoolResults)                                 \
    PFN_DEF(vkCreateBuffer)                                        \
    PFN_DEF(vkDestroyBuffer)                                       \
    PFN_DEF(vkCreateBufferView)                                    \
    PFN_DEF(vkDestroyBufferView)                                   \
    PFN_DEF(vkCreateImage)                                         \
    PFN_DEF(vkDestroyImage)                                        \
    PFN_DEF(vkGetImageSubresourceLayout)                           \
    PFN_DEF(vkCreateImageView)                                     \
    PFN_DEF(vkDestroyImageView)                                    \
    PFN_DEF(vkCreateShaderModule)                                  \
    PFN_DEF(vkDestroyShaderModule)                                 \
    PFN_DEF(vkCreatePipelineCache)                                 \
    PFN_DEF(vkDestroyPipelineCache)                                \
    PFN_DEF(vkGetPipelineCacheData)                                \
    PFN_DEF(vkMergePipelineCaches)                                 \
    PFN_DEF(vkCreateGraphicsPipelines)                             \
    PFN_DEF(vkCreateComputePipelines)                              \
    PFN_DEF(vkDestroyPipeline)                                     \
    PFN_DEF(vkCreatePipelineLayout)                                \
    PFN_DEF(vkDestroyPipelineLayout)                               \
    PFN_DEF(vkCreateSampler)                                       \
    PFN_DEF(vkDestroySampler)                                      \
    PFN_DEF(vkCreateDescriptorSetLayout)                           \
    PFN_DEF(vkDestroyDescriptorSetLayout)                          \
    PFN_DEF(vkCreateDescriptorPool)                                \
    PFN_DEF(vkDestroyDescriptorPool)                               \
    PFN_DEF(vkResetDescriptorPool)                                 \
    PFN_DEF(vkAllocateDescriptorSets)                              \
    PFN_DEF(vkFreeDescriptorSets)                                  \
    PFN_DEF(vkUpdateDescriptorSets)                                \
    PFN_DEF(vkCreateFramebuffer)                                   \
    PFN_DEF(vkDestroyFramebuffer)                                  \
    PFN_DEF(vkCreateRenderPass)                                    \
    PFN_DEF(vkDestroyRenderPass)                                   \
    PFN_DEF(vkGetRenderAreaGranularity)                            \
    PFN_DEF(vkCreateCommandPool)                                   \
    PFN_DEF(vkDestroyCommandPool)                                  \
    PFN_DEF(vkResetCommandPool)                                    \
    PFN_DEF(vkAllocateCommandBuffers)                              \
    PFN_DEF(vkFreeCommandBuffers)                                  \
    PFN_DEF(vkBeginCommandBuffer)                                  \
    PFN_DEF(vkEndCommandBuffer)                                    \
    PFN_DEF(vkResetCommandBuffer)                                  \
    PFN_DEF(vkCmdBindPipeline)                                     \
    PFN_DEF(vkCmdSetViewport)                                      \
    PFN_DEF(vkCmdSetScissor)                                       \
    PFN_DEF(vkCmdSetLineWidth)                                     \
    PFN_DEF(vkCmdSetDepthBias)                                     \
    PFN_DEF(vkCmdSetBlendConstants)                                \
    PFN_DEF(vkCmdSetDepthBounds)                                   \
    PFN_DEF(vkCmdSetStencilCompareMask)                            \
    PFN_DEF(vkCmdSetStencilWriteMask)                              \
    PFN_DEF(vkCmdSetStencilReference)                              \
    PFN_DEF(vkCmdBindDescriptorSets)                               \
    PFN_DEF(vkCmdBindIndexBuffer)                                  \
    PFN_DEF(vkCmdBindVertexBuffers)                                \
    PFN_DEF(vkCmdDraw)                                             \
    PFN_DEF(vkCmdDrawIndexed)                                      \
    PFN_DEF(vkCmdDrawIndirect)                                     \
    PFN_DEF(vkCmdDrawIndexedIndirect)                              \
    PFN_DEF(vkCmdDispatch)                                         \
    PFN_DEF(vkCmdDispatchIndirect)                                 \
    PFN_DEF(vkCmdCopyBuffer)                                       \
    PFN_DEF(vkCmdCopyImage)                                        \
    PFN_DEF(vkCmdBlitImage)                                        \
    PFN_DEF(vkCmdCopyBufferToImage)                                \
    PFN_DEF(vkCmdCopyImageToBuffer)                                \
    PFN_DEF(vkCmdUpdateBuffer)                                     \
    PFN_DEF(vkCmdFillBuffer)                                       \
    PFN_DEF(vkCmdClearColorImage)                                  \
    PFN_DEF(vkCmdClearDepthStencilImage)                           \
    PFN_DEF(vkCmdClearAttachments)                                 \
    PFN_DEF(vkCmdResolveImage)                                     \
    PFN_DEF(vkCmdSetEvent)                                         \
    PFN_DEF(vkCmdResetEvent)                                       \
    PFN_DEF(vkCmdWaitEvents)                                       \
    PFN_DEF(vkCmdPipelineBarrier)                                  \
    PFN_DEF(vkCmdBeginQuery)                                       \
    PFN_DEF(vkCmdEndQuery)                                         \
    PFN_DEF(vkCmdResetQueryPool)                                   \
    PFN_DEF(vkCmdWriteTimestamp)                                   \
    PFN_DEF(vkCmdCopyQueryPoolResults)                             \
    PFN_DEF(vkCmdPushConstants)                                    \
    PFN_DEF(vkCmdBeginRenderPass)                                  \
    PFN_DEF(vkCmdNextSubpass)                                      \
    PFN_DEF(vkCmdEndRenderPass)                                    \
    PFN_DEF(vkCmdExecuteCommands)

#define DEFINE_VK_FUNCTION_MACRO(function)                         \
    PFN_##function function;

#define GET_VK_FUNCTION_PROCADDR(function)                         \
    function = reinterpret_cast<PFN_##function>(lib.get_function<PFN_##function>(#function));

APPLY_PFN_DEF_VK_FUNCTIONS(DEFINE_VK_FUNCTION_MACRO);

void vk_loader_init()
{
    static dylib lib(VULKAN_LIB, false);
    APPLY_PFN_DEF_VK_FUNCTIONS(GET_VK_FUNCTION_PROCADDR);
}

项目实战

这是整个测试demo的项目地址:

sumcai/MiniVulkanTriangle (gitee.com)

  • 16
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值