原生和专有引擎

开始在 Android 上使用 Vulkan

Vulkan 是 Android 上主要的低级图形 API。Vulkan 为实现自己的游戏引擎和渲染器的游戏提供了最佳性能。

要在您的游戏引擎中成功实现 Vulkan,您必须:

  • 确定哪些 Android 设备支持 Vulkan
  • 了解支持旧版 Android 设备的权衡
  • 将 Vulkan 添加到您的 Android 构建目标
  • 选择着色器编译器为 Vulkan 创建 SPIR-V
  • 在运行时确定可用的 Vulkan API 版本
  • 了解如何使用 Vulkan 配置文件、帧同步和预旋转优化您的 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 Baseline profile 兼容的硬件功能和特性

旧设备支持

如果您的游戏旨在在具有不同图形功能水平的各种设备上运行,您可能需要支持比选择 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 头文件副本,或者在 Vulkan SDK 发布版本中找到打包的头文件。任何特定的 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 函数的指针。实现此目的的一种方法是使用开源元加载器库,例如 volkAGDKTunnel 示例游戏为此目的集成了 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 时,不要请求高于以下版本的 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 profile,请使用开源 Vulkan Profiles API 库。您也可以自行解析配置文件 JSON 文件,并使用相关的 Vulkan API 查询设备功能以确定配置文件兼容性。

Vulkan 配置文件

Android 正在使用 Vulkan 配置文件,它定义了每个运行 Android 的设备可用的功能和扩展。

Android Baseline Profile (ABP) 是构建 Vulkan 配置文件的首次尝试。ABP2021ABP2022 是旨在覆盖当时超过 85% 活跃设备的向后兼容配置文件。未来将不再有新的 ABP。

适用于 Android 的 Vulkan 配置文件 (VPA) 是新的前瞻性配置文件,旨在反映软件开发人员的需求,并尽快推动硬件开发人员提供一致的功能。VPA15_minimums 是 Android 15 的第一个配置文件,并且每年都会发布新的 VPA 以覆盖每个主要的 Android 版本。

实现帧同步

适当的帧同步是提供高质量游戏体验的重要组成部分。Android 游戏开发套件包含 Frame Pacing 库,可帮助您的游戏实现最佳帧同步。有关更多实现详情,请参阅将 Android Frame Pacing 集成到您的 Vulkan 渲染器中

不要依赖隐式同步和帧同步

vkAcquireNextImageKHRvkQueuePresentKHR 用于管理交换链。避免依赖它们的潜在阻塞行为来实现通用应用或 GPU 同步。

这些函数的精确阻塞行为在以下方面可能存在显著差异:

vkAcquireNextImageKHR 的唯一目的是获取可用的可呈现图像,它可能会或可能不会阻塞。类似地,vkQueuePresentKHR 将显示图像的请求排入队列,也可能会或可能不会阻塞。

这两个函数都不能为同步不相关的 CPU 任务或 GPU 操作提供可靠的保证。

为了实现稳健的同步,请始终使用显式 Vulkan 原语,例如用于 GPU-GPU 依赖项(例如,渲染到呈现)的信号量,用于 GPU-CPU 同步(例如,知道 CPU 何时完成渲染)的栅栏,以及用于更细粒度 GPU 执行和内存依赖项的管线屏障或事件。使用显式同步可确保可预测的行为,并避免因 Android 多样化硬件生态系统中固有的实现特定时序变化而导致的细微错误。

实现预旋转

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 设备满足其用例并能够流畅、无 Bug 地运行其应用。

如果您使用 Vulkan 应用程序成功触发了一个影响任何特定 Android 设备的新 Bug,您可以提交新的测试提案,描述您的问题以及检查该问题的方法。这可确保该问题在设备的未来更新中得到修复,并确保同一 Bug 不会发生在任何其他设备上。

请查看CTS 提交流程,了解如何提交测试提案的分步说明。