跳到主要内容

配置开发环境

本章节我们将介绍如何配置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的网站上免费下载:下载地址

image

安装Vulkan SDK后,需要验证显卡和驱动程序是否支持Vulkan,通过运行Vulkan SDK自带的cube.exe来完成。我们可以在Vulkan SDK安装目录下的Bin目录中找到它,运行cube.exe,可以看下到下面的窗口:

image

如果没有看到这个窗口,而是出现了错误消息,可以尝试更新显卡驱动程序到最新版本后再试,如果仍然出现错误消息,可以在显卡官网查询自己的显卡是否支持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中。

GLFW 目录

GLM

作为一个纯图形 API,Vulkan不包含线性代数库,我们需要自己找一个。GLM是专为与图形 API设计的线性代数库,它也经常和OpenGL一块使用。

GLM是一个只有头文件的库,我们只需下载它的最新版,然后将它放在一个合适的位置,就可以通过包含头文件的方式使用它。

image

配置Visual Studio

现在,可以创建一个Visual Studio工程来验证我们安装的依赖库是否可以正常工作。

首先,启动Visual Studio,然后选择Windows Destop Wizard。

VS 新的 CPP 项目

选择Console Application (.exe)应用程序类型,以便于直接将调试信息输出到控制台窗口上。另外,将Empty Project勾选上来阻止Visual Studo添加模板代码。

image

创建项目后,我们添加一个C++源代码文件到项目中。

image

image

将下面的代码拷贝到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模式都有效。

VS 打开项目属性

vs 所有配置

打开C++ -> General -> Additional Include Directories,点击Additional Include Directories的<Edit...>下拉选项。

与 CPP 通用

添加Vulkan,GLFW和GLM的头文件目录:

vs 包含目录

接着,打开Linker -> General:

VS Link 设置

添加Vulkan和GLFW的库目录:

vs 链接目录

打开 Linker -> Input,点击Additional Dependencies的<Edit...>下拉选项:

VS 链接输入

添加Vulkan和GLFW的库文件:

VS 依赖项

现在可以关闭项目属性对话框了。如果一切顺利,代码编辑器里已经没有任何高亮显示的错误了。

最后,确认代码在64位模式下编译:

VS 构建模式

然后,按下F5编译运行,你就会看到下面的窗口:

VS 测试窗口

控制台窗口显示的扩展数理应为非0,至此,我们就配置好Vulkan开发环境了!

Linux

我们使用Ubuntu来演示,其它Linux平台的配置方法应该是类似的。

Vulkan软件包

在 Linux 上开发 Vulkan 应用程序最重要的组件是 Vulkan 加载程序、校验层和用于测试机器是否支持 Vulkan的实用程序:

  • sudo apt install vulkan-toolssudo dnf install vulkan-tools :安装实用的命令行程序vulkaninfovkcube ,用来检测设备是否支持 Vulkan。
  • sudo apt install libvulkan-devsudo dnf install vulkan-loader-devel:安装 Vulkan 加载器程序。 加载程序在运行时查找驱动程序中的函数,类似于 OpenGL 的 GLEW。
  • sudo apt install vulkan-validationlayers spirv-toolssudo dnf install mesa-vulkan-devel vulkan-validation-layers-devel:安装标准校验层和 SPIR-V 工具。这些工具用于调试 Vulkan 应用程序,我们将在下一章中介绍。

在 Arch Linux 上,可以运行sudo pacman -S vulkan-devel来安装上述所有的工具。

如果安装成功,运行vkcube,可以看到下面的画面:

image

如果没有看到,而是出现了错误消息,可以尝试更新显卡的驱动程序到最新版本后再试,如果仍然出现错误消息,可以在显卡官网查询自己的显卡是否支持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需要的一些系统库:多线程和窗口管理。 如果Xxf86vmXi库没有安装,可以使用下面的命令安装:

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,你将会看到下面的窗口:

image

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项目类型:

image

接着,选择C++作为项目使用的语言:

image

现在将下面的代码作为项目的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就可以找到我们使用的库文件。

设置完成后,看起来像这样(实际内容依赖于我们自己的文件所在的位置):

image

现在,点击 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,点击+号,将所有三个动态库添加进去。

image

最后,我们需要配置环境变量。在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

完成后,看起来像这样:

image

至此为止,我们完成了全部设置,可以编译运行项目了,效果如下:

image

程序输出的日志信息中的扩展数应该是非0的 。 现在,我们已经做好开始Vulkan探险之旅的准备!