赞
踩
最近在国产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,它支持多系统平台:
以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的项目地址:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。