Vulkan 教程 Khronos Vulkan® Tutorial · 中文翻译 GitHub

本章将搭建 Vulkan 应用的开发环境,并安装一些有用的库。除了编译器之外,我们要用到的工具都兼容 Windows、Linux 和 macOS,但安装步骤略有差异,因此下面按平台分别说明。

获取代码

首先需要从 GitHub 仓库克隆教程代码。这要求先安装 git 版本控制系统。

装好 git 之后,就可以像这样在本地克隆仓库:

git clone https://github.com/KhronosGroup/Vulkan-Tutorial

这会把仓库克隆到当前目录下新建的 Vulkan-Tutorial 文件夹中,各章的源码位于 attachments 文件夹里。

依赖安装脚本

为了简化环境搭建,我们提供了 Windows 和 Linux 的依赖安装脚本:

Windows

Windows 上提供了一个用 vcpkg 安装全部依赖的脚本:

  1. 确认已安装 vcpkg;若尚未安装,请按 https://github.com/microsoft/vcpkg 上的说明操作

  2. 运行 scripts/install_dependencies_windows.bat 脚本

  3. 按提示安装 Vulkan SDK

虽然这个安装脚本借助了 vcpkg,但整个流程在下面都有详细说明,不用安装脚本、也不需要 vcpkg 同样可以完成。脚本只是为了减轻环境搭建的负担。

Linux

Linux 上提供了一个能识别包管理器并安装全部依赖的脚本:

  1. 运行 scripts/install_dependencies_linux.sh 脚本

  2. 按提示安装 Vulkan SDK

如果你更愿意手动安装依赖,或者使用的是 macOS,请参考下面各平台的具体说明。

通用要点

Vulkan SDK

开发 Vulkan 应用最需要的部分是 SDK。它包含头文件、标准验证层、调试工具,以及 Vulkan 函数的加载器。加载器会在运行时从驱动中查找函数,如果你熟悉 OpenGL 的 GLEW,可以把两者类比。

SDK 可以从 LunarG 网站下载。

按提示完成安装,并留意 SDK 的安装位置。首先我们要确认你的显卡和驱动正确支持 Vulkan。进入 SDK 的安装目录,打开 bin 目录,运行 vkcube 演示程序。

这个目录里还有一个对开发很有用的程序。slangc 命令行程序用于把人类可读的 Slang 着色语言编译成字节码,我们会在 着色器模块一章详细讨论。bin 目录里还有 Vulkan 加载器与验证层的二进制文件,lib 目录中则是库文件。

最后是 include 目录,Vulkan 头文件都在里面。其他文件可以随意浏览,但本教程用不到。

为了自动设置 VulkanSDK 用来简化 CMake 项目配置和其他工具的环境变量,Linux 上推荐使用 setup-env 脚本。你可以把这个脚本加入终端的启动配置或 IDE 设置,确保每个会话中都能使用这些环境变量。

如果收到错误信息,请确认驱动已更新、包含 Vulkan 运行时,并且你的显卡受支持。各大厂商驱动的下载链接见 简介章节。

CMake

尽管跨平台项目有种种麻烦,CMake 已经成为业内的通用工具。它让开发者可以编写一份项目级的构建描述文件,由它负责建立和配置创建项目所需的全部辅助工具。也有 bazel 之类具备类似能力的其他构建系统,但没有哪个像 CMake 这样被广泛使用和接受。完整介绍 CMake 的用法超出了本教程的范围,更多细节可以查阅 CMake 官网。

Vulkan SDK 支持使用 find_package。要在项目中使用,可以把 *-config.cmake 的搜索路径加到 find_package 配置调用的 HINTS 部分,例如:

find_package(slang CONFIG HINTS "$ENV{VULKAN_SDK}/lib/cmake")

将来 FindVulkan.cmake 可能会迁移到 *-config.cmake 标准,但撰写本文时,建议从 VulkanSamples 获取 FindVulkan.cmake,因为 Kitware 提供的那份既已废弃,在 macOS 构建中还有 bug。你可以在代码目录中找到 FindVulkan.cmake。

FindVulkan.cmake 属于项目专用文件,你可以取用后按构建环境的需要修改,也可以进一步按自己的需求定制。Khronos 在 VulkanSamples 中分发的那份经过充分测试,是一个不错的起点。

用法是把它加入 CMAKE_MODULE_PATH,像这样:

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")

这样,其他通过 Find*.cmake 分发的项目也可以放进同一个文件夹。可运行项目的示例见附带的 CMakeLists.txt。

Vulkan C++ 头文件还提供 C++ 模块。C++ 模块的一大优势是:既能享受 C++ 的各种好处,又不必承担编译时间过长的代价。使用时要针对目标设备编译 .cppm 文件。

Note

Vulkan C++ 头文件中的模块支持仍处于实验阶段,可能无法在所有编译器上工作。除非你想做实验,否则建议不要使用。

在 attachments 模板中启用 Vulkan C++20 模块,需要这样配置 CMake:

cmake -DENABLE_CPP20_MODULE=ON ..

启用之后,CMakeLists.txt 已包含自动构建该模块所需的全部指令。相关片段如下:

find_package (Vulkan REQUIRED)

# 配置 Vulkan C++ 模块(ENABLE_CPP20_MODULE=ON 时启用)
add_library(VulkanCppModule)
add_library(Vulkan::cppm ALIAS VulkanCppModule)

target_compile_definitions(VulkanCppModule PUBLIC
        VULKAN_HPP_DISPATCH_LOADER_DYNAMIC=1
        VULKAN_HPP_NO_STRUCT_CONSTRUCTORS=1
)

target_include_directories(VulkanCppModule PRIVATE "${Vulkan_INCLUDE_DIR}")

target_link_libraries(VulkanCppModule PUBLIC Vulkan::Vulkan)

set_target_properties(VulkanCppModule PROPERTIES CXX_STANDARD 20)

target_sources(VulkanCppModule
        PUBLIC
        FILE_SET cxx_modules TYPE CXX_MODULES
        BASE_DIRS "${Vulkan_INCLUDE_DIR}"
        FILES "${Vulkan_INCLUDE_DIR}/vulkan/vulkan.cppm"
)

VulkanCppModule 目标只需定义一次,然后把它加入使用它的项目的依赖中,它就会自动构建。你的项目不必再额外链接 Vulkan::Vulkan。

target_link_libraries (${PROJECT_NAME} Vulkan::cppm)

如果你选择保持模块关闭(默认如此),可以继续使用传统的基于头文件的包含方式(如 #include <vulkan/vulkan_raii.hpp>)。attachments 中的示例代码两种方式都能编译,只有在 ENABLE_CPP20_MODULE=ON(此时会定义 USE_CPP20_MODULES)时才会导入模块。

窗口管理

前面提到过,Vulkan 本身是平台无关的 API,不包含创建窗口、显示渲染结果的工具。为了利用 Vulkan 的跨平台优势,我们用 GLFW 库创建窗口,它支持 Windows、Linux 和 macOS。也有其他库可以做这件事,比如 SDL,但 GLFW 的优势在于,除了创建窗口,它还替我们抽象掉了 Vulkan 中一些其他平台相关的东西。

一个遗憾的缺点是 GLFW 无法在 Android 或 iOS 上工作,它只适用于桌面平台。SDL 确实提供移动端支持,不过在移动端,窗口相关支持最好还是直接与操作系统对接,例如在 Android 上使用 JNI。

GLM

与 DirectX 12 不同,Vulkan 不包含线性代数运算库,所以需要自行下载一个。http://glm.g-truc.net/[GLM] 是一个不错的库,专为图形 API 设计,在 OpenGL 中也很常用。

纹理库

Vulkan 本身不支持读取 png、jpeg、ktx 等各种纹理资源。这个话题很大,把所有格式都讲透超出了本教程的范围。本教程用 stb 作为加载纹理的依赖库。不过我们确实建议你研究一下 ktx,以充分利用这种专为图形应用设计的纹理格式。

模型库

模型格式多得数不清,暴露的细节也五花八门。一般来说,在 Vulkan 及其他图形 API 中,最重要的是顶点信息、纹理坐标,可能还有漫反射颜色细节。glTF 是一种功能丰富的高级模型格式,有跨平台库提供易于支持的特性。不过本教程为了追求简单,会使用 tinyobjloader,并且只建议在规模不大、不算复杂的项目中使用这个库。

Windows

在 Windows 上开发,用 Visual Studio 最省事。CLion 和 Android Studio 在 Windows 上也很好用,但 Visual Studio 更流行、支持更完善,所以我们在它的环境下讲依赖安装。要获得完整的 C++20 支持,需要使用高于 2019 的版本。下面的步骤基于 VS 2022 编写。

包管理

所有平台都建议使用包管理工具。Windows 本身并不依赖包管理,所以这个概念对它是陌生的。不过微软推出了一款非常好用、而且跨平台的包管理工具。VCPkg 还包含配置 CMake 所需的全部设置。关于在 Windows 项目中使用 CMake 的细节,建议参考 这份出色的文档。

这套方案让 Windows 开发者可以在 Visual Studio 中直接配合 CMake 工作,集成度相当不错。另一种选择是 CLion,它原生支持所有平台上的 CMakeLists.txt 项目,用法与 Android Studio 完全一致,而且它还是免费的 IDE。

GLFW

前面说过,建议用 vcpkg 安装软件包。在命令行中执行:vcpkg install glfw3

如果不想用 vcpkg,可以从 官方网站获取 GLFW 的最新版本。

本教程使用 64 位二进制文件,你当然也可以选择 32 位构建。那样的话,请确保链接 Lib32 目录而非 Lib 目录中的 Vulkan SDK 二进制文件。下载后把压缩包解压到一个方便的位置。我们选择在“文档”下的 Visual Studio 目录中新建一个 Libraries 目录。

glfw directory

GLM

作为纯图形 API,Vulkan 不包含线性代数运算库,所以需要自行下载一个。GLM 也可以用 vcpkg 安装:vcpkg install glm

另一种做法是直接下载 GLM,它是仅头文件的库,专为图形 API 设计,在 OpenGL 中也很常用。

library directory

tinyobjloader

tinyobjloader 可以用 vcpkg 安装:vcpkg install tinyobjloader

Linux

这些说明面向 Ubuntu、Fedora 和 Arch Linux 用户,你也可以把包管理器相关的命令换成适合自己系统的命令来跟着做。你需要一个支持 C++20 的编译器(GCC 7+ 或 Clang 5+),还需要 cmake。这些大多可以通过 build-essentials 之类的整合包安装。

我们建议使用 CLion 或其他 IDE,不过和 Linux 上的大多数事情一样,图形界面完全是可选的。

Vulkan 压缩包

在 Linux 上开发 Vulkan 应用,最重要的部分是 Vulkan 加载器、验证层,以及几个用来检测机器是否支持 Vulkan 的命令行工具:

从 LunarG 下载 VulkanSDK 压缩包。把解压后的 VulkanSDK 放到方便的路径下,再像这样为最新版本创建符号链接:

pushd vulkansdk
tar -xf vulkansdk-linux-x86_64-1.4.304.1.tar.xz
ln -s 1.4.304.1 default

然后把下面这行加入 ~/.bashrc,让 Vulkan 的环境变量在所有地方都生效:

source ~/vulkanSDK/default/setup-env.sh

如果安装成功,Vulkan 部分就都准备好了。记得运行 vkcube,确认窗口中弹出下面的画面:

cube demo nowindow

如果收到错误信息,请确认驱动已更新、包含 Vulkan 运行时,并且你的显卡受支持。各大厂商驱动的下载链接见 简介章节。

Ninja

Ninja 是一个快速的构建系统,CMake 在所有平台上都支持它。建议用 sudo apt install ninja-build 安装。

X Window System 与 XFree86-VidModeExtension

系统里可能没有这些库,如果没有,可以用下面的命令安装: * sudo apt install libxxf86vm-dev 或 dnf install libXxf86vm-devel:提供 XFree86-VidModeExtension 的接口。 * sudo apt install libxi-dev 或 dnf install libXi-devel:提供 X Window System 访问 XINPUT 扩展的客户端接口。

GLFW

用下面的命令安装 GLFW:

sudo apt install libglfw3-dev

或

sudo dnf install glfw-devel

或

sudo pacman -S glfw

GLM

这是一个仅头文件的库,可以从 libglm-dev 或 glm-devel 包安装:

sudo apt install libglm-dev

或

sudo dnf install glm-devel

或

sudo pacman -S glm

配置 CLion(可选)

可以从那里获取 CLion。建议通过 JetBrains Toolbox 安装,这样 CLion 能自动保持更新。要使用 CLion 这类 IDE,需要手动设置环境变量,而在终端中运行时这些变量本会自动设置好:

source ~/vulkanSDK/default/setup-env.sh

具体做法是:打开“设置(Settings)”,选择“构建、执行、部署(Build, Execution, Deployment)”,再选择 CMake。窗口底部是环境变量一栏,在其中添加 VULKAN_SDK=<fullPathToVulkanSDK>,Vulkan 就能在编译期被找到。注意完整路径并不只是 VulkanSDK 的顶层文件夹。可以在终端中运行下面的命令来查询准确路径:

echo $VULKAN_SDK

为了方便,至少为了运行时,建议把层安装到系统全局。在终端中执行:

sudo cp $VULKAN_SDK/lib/libVkLayer_*.so /usr/local/lib/
sudo mkdir -p /usr/local/share/vulkan/explicit_layer.d
sudo cp $VULKAN_SDK/share/vulkan/explicit_layer.d/VkLayer_*.json /usr/local/share/vulkan/explicit_layer.d

另一种做法是给系统环境变量添加 VK_LAYER_PATH,指向 $VULKAN_SDK/share/vulkan/explicit_layer.d;同时还要把 $VULKAN_SDK/lib 路径加入 LD_LIBRARY_CONFIG。使用终端时,这些都由 setup-env.sh 替你完成。

搭建 CMake 项目

依赖都装好之后,就可以为 Vulkan 建立一个基础的 CMake 项目,写一点代码来确认一切正常。

我们假设你已经对 CMake 有基本了解,比如变量和规则如何工作。如果没有,可以通过 这份教程快速上手。

现在可以把本教程的 attachments 目录当作 Vulkan 项目的模板。复制一份,重命名为 HelloTriangle 之类的名字,并清空 main.cpp 中的所有代码。

现在你已经准备好迎接 真正的冒险了。

macOS

这些说明假设你使用 Xcode 和 Homebrew 包管理器。另外要注意,macOS 版本至少需要 10.11,设备还需支持 Metal API。

Vulkan SDK

macOS 版 SDK 内部使用 MoltenVK。macOS 没有 Vulkan 的原生支持,MoltenVK 实际上充当一层转换,把 Vulkan API 调用翻译成 Apple 的 Metal 图形框架调用。借此你可以利用 Metal 框架在调试和性能上的优势。

下载 macOS 安装程序后,双击安装并跟随提示操作。在“安装文件夹(Installation Folder)”一步要记下安装位置,之后在 Xcode 中创建项目时会用到。

sdk install mac

注意:本教程中,vulkansdk 指你安装 VulkanSDK 的路径。

在 vulkansdk/Applications 文件夹中,应该有一些可执行文件,可以用 SDK 运行几个演示程序。运行 vkcube,你会看到下面的画面:

cube demo mac

GLFW

在 macOS 上安装 GLFW,我们用 Homebrew 包管理器获取 glfw 包:

brew install glfw

GLM

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

brew install glm

配置 Xcode

依赖都安装好之后,就可以为 Vulkan 建立基础的 Xcode 项目了。这里的多数说明其实就是一堆“管道工作”,目的是把所有依赖链接到项目里。另外要记住,下文提到 vulkansdk 文件夹时,指的都是解压 Vulkan SDK 的位置。

我们建议处处使用 CMake,Apple 平台也不例外。Apple 平台上使用 CMake 的示例见 这里,VulkanSamples 项目中也有在 Apple 环境使用 CMake 项目的文档,同时面向 iOS 和桌面版 Apple 平台。

用 CMake 配合 XCode 生成器之后,打开生成的 Xcode 项目。如果你用的是本教程的代码目录,可以在命令行中这样做:

cd code
cmake -G XCode

最后需要设置几个环境变量。在 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

取消勾选“shared”。它看起来应该像这样:

xcode variables

至此,一切就绪!

现在你已经准备好迎接 真正的内容了。

Android

Vulkan 在 Android 上是一等 API,支持广泛。但它的用法在窗口管理、构建系统等几个关键方面与桌面平台不同。因此,基础章节虽然聚焦桌面平台,教程还专门准备了 一章,带你搭建 Android 开发环境并让教程代码在 Android 上跑起来。

搭建 CMake 项目

依赖都装好之后,就可以为 Vulkan 建立一个基础的 CMake 项目,写一点代码来确认一切正常。

我们假设你已经对 CMake 有基本了解,比如变量和规则如何工作。如果没有,可以通过 这份教程快速上手。

attachment\template 文件夹里有一个 CMake 模板,可以用它为你在 build 文件夹中生成所选用 IDE 的项目文件。把它作为跟随教程动手的起点:

cd attachments\template
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=[path\to\vcpkg]\scripts\buildsystems\vcpkg.cmake

也可以在 attachments 文件夹中做同样的事,这样会生成包含教程所有章节的项目:

cd attachments
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=[path\to\vcpkg]\scripts\buildsystems\vcpkg.cmake

恭喜,你已经准备好 上手 Vulkan了!