配置开发环境
本章节我们将介绍如何配置Vulkan SDK和一些非常有用的库。这里用到的工具除了编译器,其它均适用于Windows,Linux和MacOS这三个平台,但它们的安装方法可能会在各平台有所不同,所以我们分别描述每个平台的配置方法。
Windows
我们这里使用Visual Studio 2017作为Windows平台的开发环境,使用其他Visual Studio版本应该也不会有问题,只是配置方法可能会略微不同。
Vulkan SDK
Vulkan SDK是开发Vulkan应用程序必不可少的组件,它包含Vulkan API的标准头文件,标准校验层实现、调试工具和Vulkan函数加载器。Vulkan函数加载器类似OpenGL的GLEW可以在运行时查询驱动程序支持的Vulkan API函数。
Vulkan SDK可以从LunarG的网站上免费下载:下载地址
安装Vulkan SDK后,需要验证显卡和驱动程序是否支持Vulkan,通过运行Vulkan SDK自带的cube.exe来完成。我们可以在Vulkan SDK安装目录下的Bin目录中找到它,运行cube.exe,可以看下到下面的窗口:
如果没有看到这个窗口,而是出现了错误消息,可以尝试更新显卡驱动程序到最新版本后再试,如果仍然出现错误消息,可以在显卡官网查询自己的显卡是否支持Vukan。
在Bin目录下还有一个非常有用的程序:glslangValidator.exe。它可以将GLSL着色器代码编译为字节码。我们将在着色器模块章节详细说明。除此之外,Bin目录下还包含了Vulkan函数加载器和校验层的二进制文件,它们的库文件则位于Vulkan SDK的Lib目录下。
Vulkan SDK的Documentation目录包含了Vulkan SDK的离线文档和完整的Vulkan规范文档。最后是Vulkan SDK的Include目录,它包含了Vulkan API的标准头文件。除此之外,还有很多文件和目录,但本教程没有使用到,所以就不再一一介绍。
GLFW
之前提到,Vulkan是一个平台无关的图形API,它不包含任何创建窗口的功能。为了实现跨平台的优势而避免陷入Win32的窗口细节中,我们使用GLFW库来实现窗口的相关操作。GLFW库也是跨平台的,支持Windows,Linux和MacOS。当然,还有其它一些库可以完成类似功能,比如SDL。但除了窗口功能,GLFW库还抽象出了Vulkan其他一些平台无关的特性,所以我们选用它。
读者可以在GLFW官方网站上免费下载到最新版本的GLFW库。本教程使用64位版本的GLFW库,32位版本也是可以的,只是编译Vulkan应用程序时也需要链接到32位版本的Vulkan SDK,也就是链接到Vulkan SDK下Lib32目录中的库。下载GLFW后,将它解压缩到一个合适的 位置。这里我们将它解压到Visual Studio目录下的Libraries中。
GLM
作为一个纯图形 API,Vulkan不包含线性代数库,我们需要自己找一个。GLM是专为与图形 API设计的线性代数库,它也经常和OpenGL一块使用。
GLM是一个只有头文件的库,我们只需下载它的最新版,然后将它放在一个合适的位置,就可以通过包含头文件的方式使用它。
配置Visual Studio
现在,可以创建一个Visual Studio工程来验证我们安装的依赖库是否可以正常工作。
首先,启动Visual Studio,然后选择Windows Destop Wizard。
选择Console Application (.exe)应用程序类型,以便于直接将调试信息输出到控制台窗口上。另外,将Empty Project勾选上来阻止Visual Studo添加模板代码。
创建项目后,我们添加一个C++源代码文件到项目中。
将下面的代码拷贝到C++源文件中。代码内容暂时不需要理解,现在只是为了验证我们的依赖库是否配置正确,我们将会在后面的章节详细讲解代码内容。
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/vec4.hpp>
#include <glm/mat4x4.hpp>
#include <iostream>
int main() {
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(800, 600, "Vulkan window", nullptr, nullptr);
uint32_t extensionCount = 0;
vkEnumerateInstanceExtensionProperties(nullptr,
&extensionCount, nullptr);
std::cout << extensionCount << " extensions supported" << std::endl;
glm::mat4 matrix;
glm::vec4 vec;
auto test = matrix * vec;
while(!glfwWindowShouldClose(window)) {
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
配置项目属性,选择All Configurations,让设置对Debug和Release模式都有效。
打开C++ -> General -> Additional Include Directories,点击Additional Include Directories的<Edit...>
下拉选项。
添加Vulkan,GLFW和GLM的头文件目录:
接着,打开Linker -> General:
添加Vulkan和GLFW的库目录:
打开 Linker -> Input,点击Additional Dependencies的<Edit...>
下拉选项:
添加Vulkan和GLFW的库文件:
现在可以关闭项目属性对话框了。如果一切顺利,代码编辑器里已经没有任何高亮显示的错误了。
最后,确认代码在64位模式下编译:
然后,按下F5编译运行,你就会看到下面的窗口:
控制台窗口显示的扩展数理应为非0,至此,我们就配置好Vulkan开发环境了!
Linux
我们使用Ubuntu来演示,其它Linux平台的配置方法应该是类似的。
Vulkan软件包
在 Linux 上开发 Vulkan 应用程序最重要的组件是 Vulkan 加载程序、校验层和用于测试机器是否支持 Vulkan的实用程序:
sudo apt install vulkan-tools
或sudo dnf install vulkan-tools
:安装实用的命令行程序vulkaninfo
和vkcube
,用来检测设备是否支持 Vulkan。sudo apt install libvulkan-dev
或sudo dnf install vulkan-loader-devel
:安装 Vulkan 加载器程序。 加载程序在运行时查找驱动程序中的函数,类似于 OpenGL 的 GLEW。sudo apt install vulkan-validationlayers spirv-tools
或sudo dnf install mesa-vulkan-devel vulkan-validation-layers-devel
:安装标准校验层和 SPIR-V 工具。这些工具用于调试 Vulkan 应用程序,我们将在下一章中介绍。
在 Arch Linux 上,可以运行sudo pacman -S vulkan-devel
来安装上述所有的工具。
如果安装成功,运行vkcube,可以看到下面的画面:
如果没有看到,而是出现了错误消息,可以尝试更新显卡的驱动程序到最新版本后再试,如果仍然出现错误消息, 可以在显卡官网查询自己的显卡是否支持Vukan。
GLFW
我们通过以下命令安装 GLFW:
sudo apt install libglfw3-dev
或
sudo dnf install glfw-devel
或
sudo pacman -S glfw
GLM
我们通过以下命令安装GLM:
sudo apt install libglm-dev
或
sudo dnf install glm-devel
或
sudo pacman -S glm
着色器编译器
我们需要一个程序将着色器从人类可读的 GLSL 代码编译为字节码。
当前有两种最流行的着色器编译器:Khronos Group的 glslangValidator 和 Google 的glslc。glslc 的用法类似于GCC 和 Clang,这里我们采用glslc。
下载glslc,并将它拷贝到目录/usr/local/bin
,下载地址
直接运行glslc查看是否能运行:glslc: error: no input files
。
我们将在着色器模块一章中详细介绍glslc。
配置makefile文件
现在,我们已经安装完了所有的依赖项,可以开始配置应用程序的makefile。
新建一个VulkanTest文件夹,然后在文件夹里创建main.cpp文件并拷贝如下代码:
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/vec4.hpp>
#include <glm/mat4x4.hpp>
#include <iostream>
int main() {
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(800, 600, "Vulkan
window", nullptr, nullptr);
uint32_t extensionCount = 0;
vkEnumerateInstanceExtensionProperties(nullptr,
&extensionCount, nullptr);
std::cout << extensionCount << " extensions supported" << std::endl;
glm::mat4 matrix;
glm::vec4 vec;
auto test = matrix * vec;
while(!glfwWindowShouldClose(window)) {
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
源代码的内容暂时不需要理解,现在只是为了验证 依赖是否配置正确,源代码的内容,将在后面的章节详细说明。
接着,需要编写makefile来编译源代码。这里假设读者具有一定makefile使用经验,知道makefile的变量和规则的用法。如果没有用过,可以从[这个教程](Makefile Tutorial By Example)快速学习。
我们首先定义一些变量来简化makefile。定义CFLAGS变量来指定C++ 11来编译源代码:
CFLAGS = -std=c++11
然后,定义LDFLAGS变量来指定链接选项:
LDFLAGS = -lglfw -lvulkan -ldl -lpthread -lX11 -lXxf86vm -lXrandr -lXi
-lglfw
用于链接GLFW,-lvulkan
用于链接vulkan加载器。其他的flag是GLFW需要的一些系统库:多线程和窗口管理。 如果Xxf86vm
和Xi
库没有安装,可以使用下面的命令安装:
sudo apt install libxxf86vm-dev libxi-dev
或
sudo dnf install libXi-devel libXxf86vm-devel
或
sudo pacman -S libxi libxxf86vm
现在可以定义编译VulkanTest的规则了,确保使用tab缩进,而不是空格:
VulkanTest: main.cpp
g++ $(CFLAGS) -o VulkanTest main.cpp $(LDFLAGS)
将上面的代码保存为Makefile文件,然后使用终端在Makefile文件所在目录执行make命令。如果一切顺利,会生成一个VulkanTest可执行文件。
现在,我们定义另外两个规则,test和clean,前一个规则用于运行生成的可执行文件,后一个规则用于清除生成的可执行文件:
.PHONY: test clean
test: VulkanTest
./VulkanTest
clean:
rm -f VulkanTest
运行make test
就可以成功执行VulkanTest并且显示Vulkan扩展的数量,并且理应为非0。
至此,我们的Makefile文件已经编写完毕了,完整内容如下:
CFLAGS = -std=c++11
LDFLAGS = -lglfw -lvulkan -ldl -lpthread -lX11 -lXxf86vm -lXrandr -lXi
VulkanTest: main.cpp
g++ $(CFLAGS) -o VulkanTest main.cpp $(LDFLAGS)
.PHONY: test clean
test: VulkanTest
./VulkanTest
clean:
rm -f VulkanTest
读者可以将刚刚配置的Makefile文 件作为一个模板在以后使用。
至此,我们已经做好开始Vulkan探险之旅的准备!
MacOS
这里假定读者使用Xcode和Homebrew包管理器。另外还需要我们的MacOS版本在10.11以上,显卡设备支持Metal API。
Vulkan SDK
Vulkan SDK是使用Vulkan开发应用程序必不可少的组件。它包含了Vulkan API的头文件,一个校验层实现,调试工具和Vulkan函数加载器。Vulkan函数加载器类似OpenGL的GLEW可以在运行时查询驱动程序支持的Vulkan API函数。
Vulkan SDK可以从LunarG的网站上免费下载:下载地址
Vulkan SDK的MacOS版本是通过MoltenVK实现的,并非原生实现,也就是说MoltenVK作为一个中间层将Vulkan API调用转换为Metal调用。这也使得我们可以直接使用Metal的调试功能进行调试。
下载Vulkan SDK后,将它解压到一个合适的位置,在解压后的目录中的Applications,可以找到一些Vulkan SDK的演示程序,运行其中的可执行文件cube,你将会看到下面的窗口:
GLFW
我们使用Homebrew包管理器来安装GLFW库。GLFW的3.2.1稳定版目前还尚未完全支持Vulkan,所以我们使用下面的代码安装glfw3包的最新版本:
brew install glfw3 --HEAD
GLM
这里我们直接在终端使用下面的代码安装它:
brew install glm
配置Xcode
现在所有的依赖项已经安装完毕,我们可以开始配置一个最基本的用于Xcode的Vulkan项目。
启动Xcode,然后新建一个Xcode项目,选择Application > Command Line Tool项目类型:
接着,选择C++作为项目使用的语言:
现在将下面的代码作为项目的main.cpp源文件的内容:
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/vec4.hpp>
#include <glm/mat4x4.hpp>
#include <iostream>
int main() {
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(800, 600, "Vulkan
window", nullptr, nullptr);
uint32_t extensionCount = 0;
vkEnumerateInstanceExtensionProperties(nullptr,
&extensionCount, nullptr);
std::cout << extensionCount << " extensions supported" << std::endl;
glm::mat4 matrix;
glm::vec4 vec;
auto test = matrix * vec;
while(!glfwWindowShouldClose(window)) {
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
源代码的内容暂时不需要理解,我们现在只是为了验证我们的依赖是否配置正确,源代码的内容,我们会在后面的章节详细说明。
现在Xcode应该会显示一些诸如库未找到的错误。我们接下来的工作就是解决这些错误。在Project Navigator面板选择我们的项目,然后打开Build Settings标签页,进行下面的操作:
- 将/usr/local/include加入Header Search Paths,这是Homebrew安装头文件的路径,我们安装的glm和glfw3的头文件都在该文件夹下,然后将vulkansdk/macOS/include加入Header Search Paths,vulkansdk为我们安装的Vulkan SDK的目录。这样Xcode就可以找到我们使用的库的头文件。
- 将/usr/local/lib加入Library Search Paths,这是Homebrew安装库文件的路径,我们安装的glm和glfw3的库文件都在该文件夹下,然后将vulkansdk/macOS/lib加入Library Search Paths,vulkansdk为我们安装的Vulkan SDK的目录。这样Xcode就可以找 到我们使用的库文件。
设置完成后,看起来像这样(实际内容依赖于我们自己的文件所在的位置):
现在,点击 Build Phases标签页,添加glfw3和vulkan框架。这里,为了简便,我们添加的是动态库(如果想要使用静态库,可以参考这些库的官方文档)。
- 对于glfw,打开/usr/local/lib目录,可以找到类似libglfw.3.x.dylib形式的文件(x是库的版本号,依赖于我们使用Homebrew下载安装的glfw的版本)。将这个文件拖拽到Linked Frameworks and Libraries标签页即可。
- 对于Vulkan,打开vulkansdk/macOS/lib目录(vulkansdk是我们的Vulkan SDK所在目录),拖拽libvulkan.1.dylib和libvulkan.1.x.xx.dylib文件到Linked Frameworks and Libraries标签页即可。
完成上面的操作后,更改Copy Files标签页下的Destination为Frameworks,然后清空Subpath文本框,去掉勾选Copy only when installing,点击+号,将所有三个动态库添加进去。
最后,我们需要配置环境变量。在Xcode的工具栏上通过Product > Scheme > Edit Scheme...打开Arguments标签页,添加下面的环境变量:
- VK_ICD_FILENAMES = vulkansdk/macOS/etc/vulkan/icd.d/MoltenVK_icd.json
- VK_LAYER_PATH = vulkansdk/macOS/etc/vulkan/explicit_layer.d
完成后,看起来像这样:
至此为止,我们完成了全部设置,可以编译运行项目了,效果如下:
程序输出的日志信息中的扩展数应该是非0的 。 现在,我们已经做好开始Vulkan探险之旅的准 备!