开发环境

在本章中,我们将设置开发 Vulkan 应用程序的环境并安装一些有用的库。我们使用的所有工具(编译器除外)都与 Windows、Linux 和 MacOS 兼容,但安装步骤略有不同,因此在此处单独描述。

Windows

如果您正在为 Windows 进行开发,那么我将假设您正在使用 Visual Studio 来编译您的代码。为了完全支持 C++17,您需要使用 Visual Studio 2017 或 2019。下面概述的步骤是为 VS 2017 编写的。

Vulkan SDK

开发 Vulkan 应用程序最重要的组件是 SDK。它包括 Vulkan 函数的头文件、标准验证层、调试工具和加载器。加载器在运行时在驱动程序中查找函数,类似于 OpenGL 的 GLEW - 如果您熟悉它。

可以从 LunarG 网站使用页面底部的按钮下载 SDK。您不必创建帐户,但它可以让您访问一些可能对您有用的其他文档。

vulkan sdk download buttons

完成安装并注意 SDK 的安装位置。我们要做的第一件事是验证您的显卡和驱动程序是否正确支持 Vulkan。转到安装 SDK 的目录,打开 Bin 目录并运行 vkcube.exe 演示。您应该看到以下内容

cube demo

如果您收到错误消息,请确保您的驱动程序是最新的,包括 Vulkan 运行时,并且您的显卡受支持。有关主要供应商的驱动程序的链接,请参阅简介章节

此目录中还有另一个程序对开发很有用。 glslangValidator.exeglslc.exe 程序将用于将人类可读的 GLSL 中的着色器编译为字节码。我们将在 着色器模块章节中深入介绍这一点。 Bin 目录还包含 Vulkan 加载器和验证层的二进制文件,而 Lib 目录包含库。

最后,Include 目录包含 Vulkan 头文件。您可以随意浏览其他文件,但本教程不需要它们。

GLFW

如前所述,Vulkan 本身是一个平台无关的 API,不包括用于创建窗口来显示渲染结果的工具。为了利用 Vulkan 的跨平台优势并避免 Win32 的恐怖,我们将使用 GLFW 库来创建一个支持 Windows、Linux 和 MacOS 的窗口。还有其他库可用于此目的,例如 SDL,但 GLFW 的优点是它还在 Vulkan 中抽象了一些其他平台特定的内容,而不仅仅是窗口创建。

您可以在 官方网站上找到 GLFW 的最新版本。在本教程中,我们将使用 64 位二进制文件,但您当然也可以选择以 32 位模式构建。在这种情况下,请确保链接到 Lib32 目录而不是 Lib 中的 Vulkan SDK 二进制文件。下载后,将存档解压到方便的位置。我选择在文档下的 Visual Studio 目录中创建一个 Libraries 目录。

glfw directory

GLM

作为纯图形 API,Vulkan 不包括用于线性代数运算的库,因此我们将必须下载一个。GLM 是一个不错的库,专为与图形 API 一起使用而设计,并且也常用于 OpenGL。

GLM 是一个仅包含头文件的库,因此只需下载 最新版本并将其存储在方便的位置。您现在应该具有类似于以下目录结构

library directory

设置 Visual Studio

现在您已经安装了所有依赖项,我们可以为 Vulkan 设置一个基本的 Visual Studio 项目并编写少量代码,以确保一切正常。

启动 Visual Studio 并通过输入名称并按 确定 创建一个新的 Windows 桌面向导项目。

vs new cpp project

确保选择 控制台应用程序 (.exe) 作为应用程序类型,以便我们有一个地方可以打印调试消息,并选中 空项目 以防止 Visual Studio 添加样板代码。

vs application settings

确定 创建项目并添加 C++ 源文件。您应该已经知道如何执行此操作,但此处包含这些步骤以确保完整性。

vs new item
vs new source file

现在将以下代码添加到文件中。现在不用担心试图理解它;我们只是确保您可以编译和运行 Vulkan 应用程序。我们将在下一章从头开始。

#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\n";

    glm::mat4 matrix;
    glm::vec4 vec;
    auto test = matrix * vec;

    while(!glfwWindowShouldClose(window)) {
        glfwPollEvents();
    }

    glfwDestroyWindow(window);

    glfwTerminate();

    return 0;
}

现在让我们配置项目以消除错误。打开项目属性对话框并确保选择 所有配置,因为大多数设置都适用于 DebugRelease 模式。

vs open project properties
vs all configs

转到 C++ -> 常规 -> 其他包含目录,然后在下拉框中按 <编辑...>

vs cpp general

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

vs include dirs

接下来,在 链接器 -> 常规 下打开库目录的编辑器

vs link settings

并添加 Vulkan 和 GLFW 的对象文件的位置

vs link dirs

转到 链接器 -> 输入,然后在 其他依赖项 下拉框中按 <编辑...>

vs link input

输入 Vulkan 和 GLFW 对象文件的名称

vs dependencies

最后将编译器更改为支持 C++17 功能

vs cpp17

您现在可以关闭项目属性对话框。如果您一切操作都正确,那么您应该不再看到代码中突出显示的任何错误。

最后,请确保您实际上是在 64 位模式下进行编译。

vs build mode

F5 编译并运行项目,您应该会看到一个命令提示符和一个像这样的窗口弹出。

vs test window

扩展程序的数量应该是非零的。恭喜,您已准备好开始使用 Vulkan了!

Linux

这些说明将针对 Ubuntu、Fedora 和 Arch Linux 用户,但您可以通过将特定于包管理器的命令更改为适合您的命令来跟随操作。您应该有一个支持 C++17 的编译器(GCC 7+ 或 Clang 5+)。您还需要 make

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 来安装上述所有必需的工具。

如果安装成功,您应该已经完成了 Vulkan 部分的设置。请记住运行 vkcube 并确保您看到以下窗口弹出。

cube demo nowindow

如果您收到错误消息,请确保您的驱动程序是最新的,包括 Vulkan 运行时,并且您的显卡受支持。有关主要供应商的驱动程序的链接,请参阅简介章节

X Window 系统和 XFree86-VidModeExtension

这些库可能不在系统上,如果不是,您可以使用以下命令安装它们。

  • sudo apt install libxxf86vm-devdnf install libXxf86vm-devel:提供 XFree86-VidModeExtension 的接口。

  • sudo apt install libxi-devdnf install libXi-devel:提供 X Window 系统客户端接口,用于 XINPUT 扩展。

GLFW

如前所述,Vulkan 本身是一个与平台无关的 API,不包括创建窗口以显示渲染结果的工具。为了利用 Vulkan 的跨平台优势并避免 X11 的恐怖,我们将使用 GLFW 库来创建一个窗口,该窗口支持 Windows、Linux 和 MacOS。还有其他可用于此目的的库,例如 SDL,但 GLFW 的优势在于,它还抽象了 Vulkan 中除窗口创建之外的其他一些特定于平台的事情。

我们将通过以下命令安装 GLFW。

sudo apt install libglfw3-dev

sudo dnf install glfw-devel

sudo pacman -S glfw

GLM

作为纯图形 API,Vulkan 不包括用于线性代数运算的库,因此我们将必须下载一个。GLM 是一个不错的库,专为与图形 API 一起使用而设计,并且也常用于 OpenGL。

它是一个仅标头的库,可以从 libglm-devglm-devel 包中安装。

sudo apt install libglm-dev

sudo dnf install glm-devel

sudo pacman -S glm

着色器编译器

我们几乎拥有了我们需要的一切,除了我们还需要一个程序将着色器从人类可读的 GLSL 编译为字节码。

两个流行的着色器编译器是 Khronos Group 的 glslangValidator 和 Google 的 glslc。后者具有类似于 GCC 和 Clang 的用法,因此我们将使用它:在 Ubuntu 上,下载 Google 的 非官方二进制文件并将 glslc 复制到您的 /usr/local/bin。请注意,您可能需要 sudo,具体取决于您的权限。在 Fedora 上使用 sudo dnf install glslc,而在 Arch Linux 上运行 sudo pacman -S shaderc。要进行测试,请运行 glslc,它应该会正确地抱怨我们没有传递任何要编译的着色器。

glslc: 错误:没有输入文件

我们将在着色器模块一章中深入介绍 glslc

设置 Makefile 项目

现在您已经安装了所有依赖项,我们可以为 Vulkan 设置一个基本的 Makefile 项目,并编写少量代码以确保一切正常工作。

在方便的位置创建一个名为 VulkanTest 的新目录。创建一个名为 main.cpp 的源文件,并插入以下代码。现在不要担心尝试理解它;我们只是要确保您可以编译和运行 Vulkan 应用程序。我们将在下一章从头开始。

#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\n";

    glm::mat4 matrix;
    glm::vec4 vec;
    auto test = matrix * vec;

    while(!glfwWindowShouldClose(window)) {
        glfwPollEvents();
    }

    glfwDestroyWindow(window);

    glfwTerminate();

    return 0;
}

接下来,我们将编写一个 Makefile 来编译和运行此基本的 Vulkan 代码。创建一个名为 Makefile 的新空文件。我假设您已经有一些关于 Makefile 的基本经验,例如变量和规则的工作方式。如果不是,您可以通过本教程快速上手。

我们将首先定义几个变量以简化文件的其余部分。定义一个 CFLAGS 变量,该变量将指定基本的编译器标志。

CFLAGS = -std=c++17 -O2

我们将使用现代 C++ (-std=c++17),并将优化级别设置为 O2。我们可以删除 -O2 以更快地编译程序,但我们应该记住在发布版本中将其放回。

类似地,在 LDFLAGS 变量中定义链接器标志。

LDFLAGS = -lglfw -lvulkan -ldl -lpthread -lX11 -lXxf86vm -lXrandr -lXi

标志 -lglfw 用于 GLFW,-lvulkan 与 Vulkan 函数加载器链接,其余标志是 GLFW 需要的底层系统库。其余标志是 GLFW 本身的依赖项:线程和窗口管理。

Xxf86vmXi 库可能尚未安装在您的系统上。您可以在以下软件包中找到它们。

sudo apt install libxxf86vm-dev libxi-dev

sudo dnf install libXi-devel libXxf86vm-devel

sudo pacman -S libxi libxxf86vm

现在,指定编译 VulkanTest 的规则非常简单。确保使用制表符而不是空格进行缩进。

VulkanTest: main.cpp
	g++ $(CFLAGS) -o VulkanTest main.cpp $(LDFLAGS)

通过保存 Makefile 并在包含 main.cppMakefile 的目录中运行 make 来验证此规则是否有效。这应该会导致生成一个 VulkanTest 可执行文件。

我们现在将定义另外两个规则 testclean,前者将运行可执行文件,而后者将删除已构建的可执行文件。

.PHONY: test clean

test: VulkanTest
	./VulkanTest

clean:
	rm -f VulkanTest

运行 make test 应该会显示程序成功运行,并显示 Vulkan 扩展的数量。当您关闭空窗口时,应用程序应该以成功返回码 (0) 退出。您现在应该有一个完整的 Makefile,它类似于以下内容。

如果您使用的是 Wayland,并且窗口没有显示出来:别担心。Wayland 合成器可能只在应用程序实际呈现某些内容时才显示窗口。一旦我们到达我们实际呈现到窗口的第一章,窗口将开始在 Wayland 上显示出来。
CFLAGS = -std=c++17 -O2
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

您现在可以使用此目录作为 Vulkan 项目的模板。创建一个副本,将其重命名为类似 HelloTriangle 的名称,并删除 main.cpp 中的所有代码。

您现在已经为真正的冒险做好了一切准备。

MacOS

这些说明将假定您正在使用 Xcode 和 Homebrew 包管理器。此外,请记住,您至少需要 MacOS 版本 10.11,并且您的设备需要支持 Metal API

Vulkan SDK

开发 Vulkan 应用程序最重要的组件是 SDK。它包括 Vulkan 函数的头文件、标准验证层、调试工具和加载器。加载器在运行时在驱动程序中查找函数,类似于 OpenGL 的 GLEW - 如果您熟悉它。

可以从 LunarG 网站使用页面底部的按钮下载 SDK。您不必创建帐户,但它可以让您访问一些可能对您有用的其他文档。

vulkan sdk download buttons

MacOS 的 SDK 版本内部使用 MoltenVK。MacOS 本身不原生支持 Vulkan,因此 MoltenVK 实际上充当了一个中间层,将 Vulkan API 调用转换为 Apple 的 Metal 图形框架。这样,您就可以利用 Apple Metal 框架的调试和性能优势。

下载后,只需将内容解压到您选择的文件夹中(请记住,在 Xcode 上创建项目时需要引用它)。在解压后的文件夹内,Applications 文件夹中应该有一些可执行文件,它们将使用 SDK 运行一些演示。运行 vkcube 可执行文件,您将看到以下内容

cube demo mac

GLFW

如前所述,Vulkan 本身是一个与平台无关的 API,不包含用于创建窗口以显示渲染结果的工具。我们将使用 GLFW 库来创建一个窗口,它支持 Windows、Linux 和 MacOS。还有其他可用于此目的的库,例如 SDL,但 GLFW 的优势在于它还抽象了 Vulkan 中除了窗口创建之外的一些其他特定于平台的功能。

要在 MacOS 上安装 GLFW,我们将使用 Homebrew 包管理器来获取 glfw

brew install glfw

GLM

Vulkan 不包含用于线性代数运算的库,因此我们需要下载一个。GLM 是一个不错的库,专为与图形 API 一起使用而设计,并且也常用于 OpenGL。

它是一个仅包含头文件的库,可以从 glm 包安装

brew install glm

设置 Xcode

现在所有依赖项都已安装,我们可以为 Vulkan 设置一个基本的 Xcode 项目。这里的大部分说明本质上都是大量的“管道”工作,以便我们可以将所有依赖项链接到项目。此外,请记住,在以下说明中,每当我们提到文件夹 vulkansdk 时,我们指的是您解压 Vulkan SDK 的文件夹。

启动 Xcode 并创建一个新的 Xcode 项目。在将打开的窗口中,选择 Application > Command Line Tool。

xcode new project

选择 Next,为项目写一个名称,然后为 Language 选择 C++

xcode new project 2

Next,项目应该已经创建。现在,让我们将生成的 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\n";

    glm::mat4 matrix;
    glm::vec4 vec;
    auto test = matrix * vec;

    while(!glfwWindowShouldClose(window)) {
        glfwPollEvents();
    }

    glfwDestroyWindow(window);

    glfwTerminate();

    return 0;
}

请记住,您还不需要理解所有这些代码在做什么,我们只是设置一些 API 调用以确保一切正常运行。

Xcode 应该已经显示了一些错误,例如找不到库。我们现在将开始配置项目以消除这些错误。在 *项目导航器* 面板中,选择您的项目。打开 *构建设置* 选项卡,然后

  • 找到 **Header Search Paths** 字段,并添加指向 /usr/local/include 的链接(这是 Homebrew 安装头文件的地方,因此 glm 和 glfw3 头文件应该在那里)和指向 vulkansdk/macOS/include 的链接,用于 Vulkan 头文件。

  • 找到 **Library Search Paths** 字段,并添加指向 /usr/local/lib 的链接(同样,这是 Homebrew 安装库的地方,因此 glm 和 glfw3 lib 文件应该在那里)和指向 vulkansdk/macOS/lib 的链接。

它应该看起来像这样(显然,路径会因您放置文件的位置而异)

xcode paths

现在,在 *构建阶段* 选项卡中,在 **Link Binary With Libraries** 中,我们将添加 glfw3vulkan 框架。为了简化操作,我们将在项目中添加动态库(如果要使用静态框架,可以查看这些库的文档)。

  • 对于 glfw,打开文件夹 /usr/local/lib,在那里您会找到一个类似 libglfw.3.x.dylib 的文件名(“x”是库的版本号,它可能会因您从 Homebrew 下载软件包的时间而异)。只需将该文件拖到 Xcode 的 Linked Frameworks and Libraries 选项卡中。

  • 对于 vulkan,转到 vulkansdk/macOS/lib。对 libvulkan.1.dyliblibvulkan.1.x.xx.dylib 这两个文件执行相同的操作(其中“x”将是您下载的 SDK 的版本号)。

添加这些库后,在同一个选项卡的 **Copy Files** 中,将 Destination 更改为“Frameworks”,清除子路径,并取消选中“Copy only when installing”。单击“+”号,并将所有这三个框架也添加到此处。

您的 Xcode 配置应如下所示

xcode frameworks

您需要设置的最后一件事是几个环境变量。在 Xcode 工具栏中,转到 Product > Scheme > Edit Scheme...,然后在 Arguments 选项卡中添加以下两个环境变量

  • VK_ICD_FILENAMES = vulkansdk/macOS/share/vulkan/icd.d/MoltenVK_icd.json

  • VK_LAYER_PATH = vulkansdk/macOS/share/vulkan/explicit_layer.d

它应该看起来像这样

xcode variables

最后,您应该一切都设置好了!现在,如果您运行该项目(记住要根据您选择的配置将构建配置设置为 Debug 或 Release),您应该看到以下内容

xcode output

扩展的数量应该是非零的。其他日志来自库,根据您的配置,您可能会收到不同的消息。

现在,您已为 真正的内容 做好了准备。