开始在 Android 上使用 Vulkan
Vulkan 是 Android 上主要的低级图形 API。Vulkan 为实现自己的游戏引擎和渲染器的游戏提供最佳性能。
要成功地在游戏引擎中实现 Vulkan,您必须
- 确定要与 Vulkan 一起使用的 Android 设备
- 了解支持旧版 Android 设备的权衡
- 将 Vulkan 添加到您的 Android 构建目标
- 选择着色器编译器为 Vulkan 创建 SPIR-V
- 确定运行时可用的 Vulkan API 版本
- 了解如何使用 Vulkan 配置文件、帧速率控制和预旋转来优化 Vulkan 渲染操作
- 选择用于调试和性能分析的图形工具
- 注意:有关在 Unity 或 Unreal 游戏引擎中使用 Android 上的 Vulkan 的信息,请参阅
- Unity 上的 Vulkan
- Unreal 上的 Vulkan
选择 Vulkan 的最低设备规格
Vulkan 可在 Android 7.0(API 级别 24)及更高版本上使用。并非所有运行 Android 7.0 或更高版本的 Android 设备都支持 Vulkan。您需要确定您的游戏支持哪些支持 Vulkan 的 Android 设备。
建议
使用以下规格作为 Vulkan 支持的最低要求
- 设备运行 Android 10.0(API 级别 29)或更高版本
- 设备支持 Vulkan API 版本 1.1 或更高版本
- 设备具有与 2022 年 Android 基线配置文件 兼容的硬件功能和特性
旧版设备支持
如果您的游戏设计为可在各种图形功能水平不同的各种设备上运行,您可能需要支持比 选择 Vulkan 的最低设备规格 中建议的设备更旧的设备。在构建对旧版设备的支持之前,请评估 Vulkan 是否对您的游戏有益。具有大量绘制调用的游戏以及使用 OpenGL ES 的游戏可能会因在 OpenGL ES 中进行绘制调用的高成本而导致显着的驱动程序开销。这些游戏可能会因在图形驱动程序中花费大量帧时间而变得 CPU 受限。通过从 OpenGL ES 切换到 Vulkan,这些游戏还可以显着降低 CPU 和功耗。如果您游戏的场景很复杂,无法有效地使用实例化来减少绘制调用,则尤其如此。在面向旧版设备时,请包含 OpenGL ES 渲染支持作为备用方案,因为目标设备列表中的一些设备可能具有无法可靠地运行游戏的 Vulkan 实现。
您可能不希望支持旧版支持 Vulkan 的设备,因为它们缺乏性能和功能或存在稳定性问题。
性能和功能
旧版支持 Vulkan 的 Android 设备可能没有运行游戏所需的渲染性能或硬件支持功能。如果您游戏的图形保真度很高,并且 Vulkan 是您在 Android 上唯一针对的 API,则尤其如此。许多旧版设备仅限于 Vulkan API 的 1.0.3 版本,并且通常缺少在更新的硬件上可用的广泛使用的 Vulkan 扩展。
稳定性
旧版 Android 设备可能使用的是过时的 Vulkan 驱动程序。这些驱动程序版本可能包含可能影响游戏稳定性的错误。解决驱动程序错误可能需要大量测试和工程时间。
将 Vulkan 添加到您的项目
要将 Vulkan 添加到您的项目,您需要
- 包含 Vulkan API 标头
- 将着色器代码编译为 SPIR-V
- 在运行时调用 Vulkan API
包含 Vulkan API 标头
您的游戏需要包含 Vulkan API 标头文件才能编译使用 Vulkan 的代码。您可以在 Android NDK 中或 Vulkan SDK 版本 中打包的副本中找到 Vulkan 标头的副本。任何特定 NDK 版本仅包含在 NDK 发布时可用的 Vulkan 标头。如果您使用 NDK 中的 Vulkan 标头,请使用 NDK 版本 25 或更高版本,其中包含支持 Vulkan 版本 1.3 的标头文件。Vulkan SDK 具有最新版本的标头。
将着色器代码编译为 SPIR-V
Vulkan API 预期着色器程序以 SPIR-V 二进制中间格式提供。此约定与 OpenGL ES 不同,在 OpenGL ES 中,您可以以文本字符串的形式提交用 OpenGL 着色语言 (GLSL) 编写的源代码。使用着色器编译器获取用 GLSL 或 高级着色语言 (HLSL) 等着色器语言编写的代码,并将其编译成 SPIR-V 模块以用于 Vulkan。
shaderc 编译器可用于将用 GLSL 编写的着色器程序编译成 SPIR-V。如果您的游戏使用 HLSL,则 DirectXShaderCompiler 支持 SPIR-V 输出。通常,您会在游戏资产构建过程中脱机编译着色器程序,并将 SPIR-V 模块作为运行时资产的一部分包含在内。
在运行时调用 Vulkan API
要调用 Vulkan API,您的游戏需要获取指向 Vulkan API 调用的函数指针。最简单的方法是链接到 libvulkan.so
共享库,该库包含在 Android NDK 中。链接到库有两个缺点:额外的函数分派开销以及自动解析哪些 Vulkan API 函数指针的限制。
当您调用 Vulkan API 函数时,控制权将通过由称为 Vulkan 加载程序的构造管理的 分派表 传递。Android 使用自己的 Vulkan 加载程序 实现,而不是 LunarG 加载程序。此加载程序系统是 Vulkan API 层架构的一部分。在构建时链接到系统库会导致给定 API 调用的额外分派级别。虽然开销很小,但对于执行大量 Vulkan 调用的游戏来说,它可能是显而易见的。
系统库通常仅解析被认为是核心 API 一部分的 Vulkan 函数的指针。Vulkan 有大量扩展,它们定义了其他 Vulkan 函数,其中许多函数不会被系统库自动解析。在使用这些 Vulkan 函数之前,您需要手动解析指向它们的指针。
为了减轻这些问题,请在运行时动态解析指向您打算使用的所有 Vulkan 函数的指针。实现此目的的一种方法是使用开源元加载程序库,例如 volk。 AGDKTunnel 示例游戏集成了 volk 以用于此目的。如果您使用的是元加载程序库,请不要在构建脚本中链接到 libvulkan.so
共享库。
确定可用的 Vulkan API 版本
Android 支持以下 Vulkan API 版本
- 1.0.3
- 1.1
- 1.3
给定设备上可用的最高 Vulkan API 版本号由 Android 版本和 Vulkan 驱动程序支持决定。
Android 版本
对 Vulkan API 版本的平台支持取决于最低 Android 版本(API 级别)
- 1.3 — Android 13.0(API 级别 33)及更高版本
- 1.1 — Android 10.0(API 级别 29)及更高版本
- 1.0.3 — Android 7.0(API 级别 24)及更高版本
Vulkan 驱动程序支持
Android 平台对 Vulkan API 版本的支持并不能保证设备的 Vulkan 驱动程序支持该 API 版本。运行 Android 13 的设备可能仅支持 Vulkan API 的 1.1 版本。
初始化 Vulkan 时,不要请求大于
- 设备上运行的 Android 版本支持的最高 Vulkan API 版本
- vkEnumerateInstanceVersion 报告的 Vulkan API 版本
- VkPhysicalDeviceProperties 结构的
apiVersion
属性报告的 Vulkan API 版本
以下是确定最高支持的 Vulkan API 版本的示例
// Minimum Android API levels for Vulkan 1.3/1.1 version support
static constexpr int kMinimum_vk13_api_level = 33;
static constexpr int kMinimum_vk11_api_level = 29;
uint32_t GetHighestSupportedVulkanVersion(VkPhysicalDevice physical_device) {
uint32_t instance_api_version = 0;
vkEnumerateInstanceVersion(&instance_api_version);
VkPhysicalDeviceProperties device_properties;
vkGetPhysicalDeviceProperties(physical_device, &device_properties);
// Instance and device versions don't have to match, use the lowest version
// number for API support if they don't.
const uint32_t driver_api_version =
(instance_api_version < device_properties.apiVersion) ?
instance_api_version : device_properties.apiVersion;
const int device_api_level = android_get_device_api_level();
if (device_api_level >= kMinimum_vk13_api_level &&
driver_api_version >= VK_API_VERSION_1_3) {
return VK_API_VERSION_1_3;
} else if (device_api_level >= kMinimum_vk11_api_level &&
driver_api_version >= VK_API_VERSION_1_1) {
return VK_API_VERSION_1_1;
}
return VK_API_VERSION_1_0;
}
确定 Vulkan 配置文件兼容性
Vulkan 配置文件是 JSON 文件,定义了 Vulkan 设备必须支持的一组必需功能、扩展、功能和最小参数限制,才能与配置文件兼容。要确定设备是否与特定的 Vulkan 配置文件(例如 2022 年的 Android Baseline 配置文件)兼容,请使用开源的 Vulkan Profiles API 库。您也可以自己解析配置文件 JSON 文件,并使用相关的 Vulkan API 查询设备功能,以确定配置文件兼容性。
Vulkan 配置文件
Android 使用 Vulkan Profiles,它定义了运行 Android 的每个设备可用的功能和扩展。
Android Baseline Profile (ABP) 是构建 Vulkan 配置文件的首次尝试。 ABP2021 和 ABP2022 是向后兼容的配置文件,旨在覆盖当时 > 85% 的活跃设备。未来将不再有新的 ABP。
Vulkan Profiles for Android (VPA) 是新的前瞻性配置文件,旨在反映软件开发人员的需求,并在硬件开发人员能够提供功能后立即推动一致的功能。 VPA15_minimums 是 Android 15 的第一个配置文件,并且每年都会有一个新的 VPA 涵盖每个主要的 Android 版本。
实现帧速率控制
正确的帧速率控制是提供高质量游戏体验的重要组成部分。Android 游戏开发套件包含 帧速率控制库,以帮助您的游戏实现最佳的帧速率控制。有关更多实现细节,请参阅 将 Android 帧速率控制集成到您的 Vulkan 渲染器中。
实现预旋转
Android 设备可以以多种方向显示。设备方向可能与渲染面的方向不同。与 Android 上的 OpenGL ES 不同,Vulkan 不会处理两者之间的差异。要了解方向过程的工作原理以及在使用 Vulkan 时处理方向差异的最佳方法,请参阅 使用 Vulkan 预旋转处理设备旋转。
排查和分析 Vulkan 渲染
有多种工具可帮助您诊断 Vulkan 渲染代码的渲染问题和性能问题。
有关 Vulkan 调试和分析工具的更多信息,请查看 工具和高级功能 部分。
Vulkan 验证层
Vulkan 验证层是可以在运行时启用的库,用于检查您对 Vulkan API 的调用,并提供有关不正确或非最佳使用的警告或错误。默认情况下,这些验证层未处于活动状态,因为验证过程会增加运行时开销并影响游戏性能。有关如何在游戏中使用验证层的信息,请参阅 使用验证层进行调试。
帧捕获工具
使用帧捕获工具来录制和回放游戏帧期间进行的 Vulkan API 调用。这些工具允许您
- 查看活动图形资源的信息和可视化效果
- 查看游戏执行的 API 调用序列并查看 API 参数
- 探索绘制调用时图形管道的状态
- 将渲染结果可视化到帧中的特定绘制调用
使用开源的 RenderDoc 工具捕获在 Android 上运行的游戏的帧。RenderDoc 支持 Vulkan 和 OpenGL ES 的帧捕获。
Android GPU Inspector (AGI) 也可用于捕获 Vulkan 帧。
性能分析工具
使用性能分析工具来调查游戏中导致帧速率不佳的渲染问题。各个 GPU 供应商提供旨在分析您的游戏并提供特定于其 GPU 架构的性能数据的工具。当在来自不同供应商的 GPU 上渲染时,甚至在来自同一供应商的不同 GPU 代上渲染时,游戏的性能特征和瓶颈也可能存在很大差异。
您还可以使用 Android GPU Inspector 收集和分析性能数据。与供应商工具不同,Android GPU Inspector 与来自不同供应商的多个 GPU 兼容。但是,Android GPU Inspector 不支持旧版 Android 设备,并且可能与所有新设备不兼容。
使用 CTS-D 改善 Vulkan 测试
Android 设备制造商使用兼容性测试套件 (CTS) 来帮助确保其设备兼容。开发者驱动的 CTS (CTS-D) 是由 Android 应用程序开发者提交的测试,以确保未来的 Android 设备满足其用例,并能够流畅且无错误地运行其应用程序。
如果您使用 Vulkan 应用程序触发了影响任何特定 Android 设备的新错误,您可以提交新的测试提案,描述您的问题以及检查它的方法。这确保了问题在设备的未来更新中得到修复,并且还确保了相同错误不会发生在任何其他设备上。
查看 CTS 提交流程,了解有关如何提交测试提案的分步说明。