当前位置:   article > 正文

一种简单加载vulkan动态库的方法_vulkan 查找依赖库

vulkan 查找依赖库

前提

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

  1. find_package(Vulkan)
  2. if (NOT Vulkan_FOUND)
  3. find_library(Vulkan_LIBRARIES NAMES vulkan REQUIRED)
  4. endif ()
  5. include_directories(${Vulkan_INCLUDE_DIRS})
  6. 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函数地址的加载过程为例: 

  1. //加载vulkan动态库
  2. dylib lib("libvulkan.so.1", false);
  3. //定义函数指针vkCreateInstance, PFN_vkCreateInstance的声明在vulkan_core.h中
  4. PFN_vkCreateInstance vkCreateInstance;
  5. //从动态库中获取函数地址
  6. 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动态库中所有的函数地址:

  1. #include "dylib/dylib.hpp"
  2. #include "vulkan/vulkan_core.h"
  3. #if defined(WIN32) || defined(_WIN32) || defined(_WIN32_) || defined(WIN64) || defined(_WIN64) || defined(_WIN64_)
  4. #define VULKAN_LIB "vulkan-1.dll"
  5. #elif defined(ANDROID) || defined(_ANDROID_)
  6. #define VULKAN_LIB "libvulkan.so"
  7. #else
  8. #define VULKAN_LIB "libvulkan.so.1"
  9. #endif
  10. #define APPLY_PFN_DEF_VK_FUNCTIONS(PFN_DEF) \
  11. PFN_DEF(vkGetInstanceProcAddr) \
  12. PFN_DEF(vkCreateInstance) \
  13. PFN_DEF(vkEnumerateInstanceExtensionProperties) \
  14. PFN_DEF(vkEnumerateInstanceLayerProperties) \
  15. PFN_DEF(vkDestroyInstance) \
  16. PFN_DEF(vkEnumeratePhysicalDevices) \
  17. PFN_DEF(vkGetPhysicalDeviceFeatures) \
  18. PFN_DEF(vkGetPhysicalDeviceFormatProperties) \
  19. PFN_DEF(vkGetPhysicalDeviceImageFormatProperties) \
  20. PFN_DEF(vkGetPhysicalDeviceProperties) \
  21. PFN_DEF(vkGetPhysicalDeviceQueueFamilyProperties) \
  22. PFN_DEF(vkGetPhysicalDeviceMemoryProperties) \
  23. PFN_DEF(vkGetDeviceProcAddr) \
  24. PFN_DEF(vkCreateDevice) \
  25. PFN_DEF(vkDestroySurfaceKHR) \
  26. PFN_DEF(vkGetPhysicalDeviceSurfaceSupportKHR) \
  27. PFN_DEF(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) \
  28. PFN_DEF(vkGetPhysicalDeviceSurfaceFormatsKHR) \
  29. PFN_DEF(vkGetPhysicalDeviceSurfacePresentModesKHR) \
  30. PFN_DEF(vkCreateSwapchainKHR) \
  31. PFN_DEF(vkDestroySwapchainKHR) \
  32. PFN_DEF(vkGetSwapchainImagesKHR) \
  33. PFN_DEF(vkAcquireNextImageKHR) \
  34. PFN_DEF(vkQueuePresentKHR) \
  35. PFN_DEF(vkDestroyDevice) \
  36. PFN_DEF(vkEnumerateDeviceExtensionProperties) \
  37. PFN_DEF(vkEnumerateDeviceLayerProperties) \
  38. PFN_DEF(vkGetDeviceQueue) \
  39. PFN_DEF(vkQueueSubmit) \
  40. PFN_DEF(vkQueueWaitIdle) \
  41. PFN_DEF(vkDeviceWaitIdle) \
  42. PFN_DEF(vkAllocateMemory) \
  43. PFN_DEF(vkFreeMemory) \
  44. PFN_DEF(vkMapMemory) \
  45. PFN_DEF(vkUnmapMemory) \
  46. PFN_DEF(vkFlushMappedMemoryRanges) \
  47. PFN_DEF(vkInvalidateMappedMemoryRanges) \
  48. PFN_DEF(vkGetDeviceMemoryCommitment) \
  49. PFN_DEF(vkBindBufferMemory) \
  50. PFN_DEF(vkBindImageMemory) \
  51. PFN_DEF(vkGetBufferMemoryRequirements) \
  52. PFN_DEF(vkGetImageMemoryRequirements) \
  53. PFN_DEF(vkGetImageSparseMemoryRequirements) \
  54. PFN_DEF(vkGetPhysicalDeviceSparseImageFormatProperties) \
  55. PFN_DEF(vkQueueBindSparse) \
  56. PFN_DEF(vkCreateFence) \
  57. PFN_DEF(vkDestroyFence) \
  58. PFN_DEF(vkResetFences) \
  59. PFN_DEF(vkGetFenceStatus) \
  60. PFN_DEF(vkWaitForFences) \
  61. PFN_DEF(vkCreateSemaphore) \
  62. PFN_DEF(vkDestroySemaphore) \
  63. PFN_DEF(vkCreateEvent) \
  64. PFN_DEF(vkDestroyEvent) \
  65. PFN_DEF(vkGetEventStatus) \
  66. PFN_DEF(vkSetEvent) \
  67. PFN_DEF(vkResetEvent) \
  68. PFN_DEF(vkCreateQueryPool) \
  69. PFN_DEF(vkDestroyQueryPool) \
  70. PFN_DEF(vkGetQueryPoolResults) \
  71. PFN_DEF(vkCreateBuffer) \
  72. PFN_DEF(vkDestroyBuffer) \
  73. PFN_DEF(vkCreateBufferView) \
  74. PFN_DEF(vkDestroyBufferView) \
  75. PFN_DEF(vkCreateImage) \
  76. PFN_DEF(vkDestroyImage) \
  77. PFN_DEF(vkGetImageSubresourceLayout) \
  78. PFN_DEF(vkCreateImageView) \
  79. PFN_DEF(vkDestroyImageView) \
  80. PFN_DEF(vkCreateShaderModule) \
  81. PFN_DEF(vkDestroyShaderModule) \
  82. PFN_DEF(vkCreatePipelineCache) \
  83. PFN_DEF(vkDestroyPipelineCache) \
  84. PFN_DEF(vkGetPipelineCacheData) \
  85. PFN_DEF(vkMergePipelineCaches) \
  86. PFN_DEF(vkCreateGraphicsPipelines) \
  87. PFN_DEF(vkCreateComputePipelines) \
  88. PFN_DEF(vkDestroyPipeline) \
  89. PFN_DEF(vkCreatePipelineLayout) \
  90. PFN_DEF(vkDestroyPipelineLayout) \
  91. PFN_DEF(vkCreateSampler) \
  92. PFN_DEF(vkDestroySampler) \
  93. PFN_DEF(vkCreateDescriptorSetLayout) \
  94. PFN_DEF(vkDestroyDescriptorSetLayout) \
  95. PFN_DEF(vkCreateDescriptorPool) \
  96. PFN_DEF(vkDestroyDescriptorPool) \
  97. PFN_DEF(vkResetDescriptorPool) \
  98. PFN_DEF(vkAllocateDescriptorSets) \
  99. PFN_DEF(vkFreeDescriptorSets) \
  100. PFN_DEF(vkUpdateDescriptorSets) \
  101. PFN_DEF(vkCreateFramebuffer) \
  102. PFN_DEF(vkDestroyFramebuffer) \
  103. PFN_DEF(vkCreateRenderPass) \
  104. PFN_DEF(vkDestroyRenderPass) \
  105. PFN_DEF(vkGetRenderAreaGranularity) \
  106. PFN_DEF(vkCreateCommandPool) \
  107. PFN_DEF(vkDestroyCommandPool) \
  108. PFN_DEF(vkResetCommandPool) \
  109. PFN_DEF(vkAllocateCommandBuffers) \
  110. PFN_DEF(vkFreeCommandBuffers) \
  111. PFN_DEF(vkBeginCommandBuffer) \
  112. PFN_DEF(vkEndCommandBuffer) \
  113. PFN_DEF(vkResetCommandBuffer) \
  114. PFN_DEF(vkCmdBindPipeline) \
  115. PFN_DEF(vkCmdSetViewport) \
  116. PFN_DEF(vkCmdSetScissor) \
  117. PFN_DEF(vkCmdSetLineWidth) \
  118. PFN_DEF(vkCmdSetDepthBias) \
  119. PFN_DEF(vkCmdSetBlendConstants) \
  120. PFN_DEF(vkCmdSetDepthBounds) \
  121. PFN_DEF(vkCmdSetStencilCompareMask) \
  122. PFN_DEF(vkCmdSetStencilWriteMask) \
  123. PFN_DEF(vkCmdSetStencilReference) \
  124. PFN_DEF(vkCmdBindDescriptorSets) \
  125. PFN_DEF(vkCmdBindIndexBuffer) \
  126. PFN_DEF(vkCmdBindVertexBuffers) \
  127. PFN_DEF(vkCmdDraw) \
  128. PFN_DEF(vkCmdDrawIndexed) \
  129. PFN_DEF(vkCmdDrawIndirect) \
  130. PFN_DEF(vkCmdDrawIndexedIndirect) \
  131. PFN_DEF(vkCmdDispatch) \
  132. PFN_DEF(vkCmdDispatchIndirect) \
  133. PFN_DEF(vkCmdCopyBuffer) \
  134. PFN_DEF(vkCmdCopyImage) \
  135. PFN_DEF(vkCmdBlitImage) \
  136. PFN_DEF(vkCmdCopyBufferToImage) \
  137. PFN_DEF(vkCmdCopyImageToBuffer) \
  138. PFN_DEF(vkCmdUpdateBuffer) \
  139. PFN_DEF(vkCmdFillBuffer) \
  140. PFN_DEF(vkCmdClearColorImage) \
  141. PFN_DEF(vkCmdClearDepthStencilImage) \
  142. PFN_DEF(vkCmdClearAttachments) \
  143. PFN_DEF(vkCmdResolveImage) \
  144. PFN_DEF(vkCmdSetEvent) \
  145. PFN_DEF(vkCmdResetEvent) \
  146. PFN_DEF(vkCmdWaitEvents) \
  147. PFN_DEF(vkCmdPipelineBarrier) \
  148. PFN_DEF(vkCmdBeginQuery) \
  149. PFN_DEF(vkCmdEndQuery) \
  150. PFN_DEF(vkCmdResetQueryPool) \
  151. PFN_DEF(vkCmdWriteTimestamp) \
  152. PFN_DEF(vkCmdCopyQueryPoolResults) \
  153. PFN_DEF(vkCmdPushConstants) \
  154. PFN_DEF(vkCmdBeginRenderPass) \
  155. PFN_DEF(vkCmdNextSubpass) \
  156. PFN_DEF(vkCmdEndRenderPass) \
  157. PFN_DEF(vkCmdExecuteCommands)
  158. #define DEFINE_VK_FUNCTION_MACRO(function) \
  159. PFN_##function function;
  160. #define GET_VK_FUNCTION_PROCADDR(function) \
  161. function = reinterpret_cast<PFN_##function>(lib.get_function<PFN_##function>(#function));
  162. APPLY_PFN_DEF_VK_FUNCTIONS(DEFINE_VK_FUNCTION_MACRO);
  163. void vk_loader_init()
  164. {
  165. static dylib lib(VULKAN_LIB, false);
  166. APPLY_PFN_DEF_VK_FUNCTIONS(GET_VK_FUNCTION_PROCADDR);
  167. }

项目实战

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

sumcai/MiniVulkanTriangle (gitee.com)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/297926
推荐阅读
  

闽ICP备14008679号