发现一个写的比较好的基于Vulkan
的GPGPU
计算框架Vuh
,github
上的代码地址为:
1 |
https://github.com/Glavnokoman/vuh.git |
在macOS Mojave(10.14.2)
中编译方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
$ git clone https://github.com/Glavnokoman/vuh.git $ cd vuh/config $ pip install --user cget $ export PATH=/Users/`whoami`/Library/Python/2.7/bin:$PATH $ export CGET_PREFIX=. # 安装Vulkan相关依赖库 $ bash install_dependencies.sh # 指定Vulkan相关环境变量,后续的CMake文件中的FindVulkan.cmake会使用这个 $ export VULKAN_SDK=`pwd` # 我们刚刚安装的Catch2的路径,CMake需要 $ export Catch2_DIR=`pwd`/lib/cmake/Catch2 $ export ARGS=-DCatch2_DIR=$Catch2_DIR # 安装其他依赖 $ brew install spdlog $ brew install doxygen $ cd .. $ mkdir build $ cd build $ cmake .. $ARGS $ make |
如果编译的时候报错
1 2 3 4 5 6 7 8 9 10 |
Scanning dependencies of target vuh_example_spdlog [ 60%] Building CXX object doc/examples/spdlog/CMakeFiles/vuh_example_spdlog.dir/main.cpp.o /Users/xxx/Source/vuh/doc/examples/spdlog/main.cpp:14:27: error: no member named 'basic_logger_mt' in namespace 'spdlog' static auto logger = spd::basic_logger_mt("logger", "vuh.log"); ~~~~~^ 1 error generated. make[2]: *** [doc/examples/spdlog/CMakeFiles/vuh_example_spdlog.dir/main.cpp.o] Error 1 make[1]: *** [doc/examples/spdlog/CMakeFiles/vuh_example_spdlog.dir/all] Error 2 make: *** [all] Error 2 |
这个原因是由于新版本的spdlog-1.2.1
变更了basic_logger_mt
这个类的头文件。
在源代码的vuh/doc/examples/spdlog/main.cpp
中,包含如下头文件即可:
1 |
#include <spdlog/sinks/basic_file_sink.h> |
如果需要编译 Android
版本,那么如下方式进行编译:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
$ git clone https://github.com/Glavnokoman/vuh.git $ cd vuh/config $ pip install --user cget $ export PATH=/Users/`whoami`/Library/Python/2.7/bin:$PATH $ export CGET_PREFIX=. # 安装Vulkan相关依赖库 $ bash install_dependencies.sh $ export ANDROID_NDK_HOME=~/Library/Android/sdk/ndk-bundle $ cd .. $ mkdir build $ cd build $ cmake .. \ -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake \ -DANDROID_ABI="armeabi-v7a" \ -DCMAKE_BUILD_TYPE=Release \ -DANDROID_STL=c++_static \ -DANDROID_NATIVE_API_LEVEL=android-24 \ -DANDROID_TOOLCHAIN=clang \ -DVUH_BUILD_TESTS=OFF \ -DVUH_BUILD_DOCS=OFF \ -DVUH_BUILD_EXAMPLES=OFF \ -DCMAKE_CXX_FLAGS="-DVK_USE_PLATFORM_ANDROID_KHR=1 -DVULKAN_HPP_TYPESAFE_CONVERSION=1 -I$ANDROID_NDK_HOME/sources/third_party/vulkan/src/include/" # 最后生成 libvuh.so ,然后自己写代码调用这个库即可,简单的直接修改代码中的例子即可 $ make |
注意最后几个参数,文档,测试用例,例子都不参与编译,原因在于这几个工程不适合 Android
上运行,最后需要定义几个 C++
的编译宏,否则编译不通过。
如果上面编译的时候,提示如下错误信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
[ 20%] Building CXX object src/CMakeFiles/vuh.dir/instance.cpp.o vuh/src/instance.cpp:127:33: error: incompatible operand types ('vuh::debug_reporter_t' (aka 'unsigned int (*)(unsigned int, VkDebugReportObjectTypeEXT, unsigned long long, unsigned int, int, const char *, const char *, void *) __attribute__((pcs("aapcs-vfp")))') and 'auto (*)(VkDebugReportFlagsEXT, VkDebugReportObjectTypeEXT, uint64_t, size_t, int32_t, const char *, const char *, void *) -> VkBool32' (aka 'auto (*)(unsigned int, VkDebugReportObjectTypeEXT, unsigned long long, unsigned int, int, const char *, const char *, void *) -> unsigned int')) , _reporter(report_callback ? report_callback : debugReporter) ^ ~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~ vuh/src/instance.cpp:128:49: warning: field '_reporter' is uninitialized when used here [-Wuninitialized] , _reporter_cbk(registerReporter(_instance, _reporter)) ^ 1 warning and 1 error generated. make[2]: *** [src/CMakeFiles/vuh.dir/instance.cpp.o] Error 1 make[1]: *** [src/CMakeFiles/vuh.dir/all] Error 2 make: *** [all] Error 2 |
这个错误的原因是 vuh/src/instance.cpp
中定义
1 2 3 4 5 6 7 8 9 10 11 |
/// Default debug reporter used when user did not care to provide his own. static auto debugReporter( VkDebugReportFlagsEXT , VkDebugReportObjectTypeEXT, uint64_t, size_t, int32_t , const char* pLayerPrefix , const char* pMessage , void* /*pUserData*/ )-> VkBool32 { std::cerr << "[Vulkan]:" << pLayerPrefix << ": " << pMessage << "\n"; return VK_FALSE; } |
的时候,缺少 VKAPI_ATTR
这个宏。貌似只有在 Android
平台上这个宏被赋值,其他平台都是空。因此其他平台编译的时候,没有这个参数也是没问题的。
修改后的结果为:
1 2 3 4 5 6 7 8 9 10 11 |
/// Default debug reporter used when user did not care to provide his own. static auto VKAPI_ATTR debugReporter( VkDebugReportFlagsEXT , VkDebugReportObjectTypeEXT, uint64_t, size_t, int32_t , const char* pLayerPrefix , const char* pMessage , void* /*pUserData*/ )-> VkBool32 { std::cerr << "[Vulkan]:" << pLayerPrefix << ": " << pMessage << "\n"; return VK_FALSE; } |
VKAPI_ATTR
这个宏在 vk_platform.h
这个文件中被定义,定义的具体内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
/* *************************************************************************************************** * Platform-specific directives and type declarations *************************************************************************************************** */ /* Platform-specific calling convention macros. * * Platforms should define these so that Vulkan clients call Vulkan commands * with the same calling conventions that the Vulkan implementation expects. * * VKAPI_ATTR - Placed before the return type in function declarations. * Useful for C++11 and GCC/Clang-style function attribute syntax. * VKAPI_CALL - Placed after the return type in function declarations. * Useful for MSVC-style calling convention syntax. * VKAPI_PTR - Placed between the '(' and '*' in function pointer types. * * Function declaration: VKAPI_ATTR void VKAPI_CALL vkCommand(void); * Function pointer type: typedef void (VKAPI_PTR *PFN_vkCommand)(void); */ #if defined(_WIN32) // On Windows, Vulkan commands use the stdcall convention #define VKAPI_ATTR #define VKAPI_CALL __stdcall #define VKAPI_PTR VKAPI_CALL #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7 #error "Vulkan isn't supported for the 'armeabi' NDK ABI" #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE) // On Android 32-bit ARM targets, Vulkan functions use the "hardfloat" // calling convention, i.e. float parameters are passed in registers. This // is true even if the rest of the application passes floats on the stack, // as it does by default when compiling for the armeabi-v7a NDK ABI. #define VKAPI_ATTR __attribute__((pcs("aapcs-vfp"))) #define VKAPI_CALL #define VKAPI_PTR VKAPI_ATTR #else // On other platforms, use the default calling convention #define VKAPI_ATTR #define VKAPI_CALL #define VKAPI_PTR #endif |