原生和私有引擎

开始在 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 上可用。并非所有运行 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函数的指针。一种实现方法是使用开源元加载器库,例如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基线配置文件)兼容,请使用开源Vulkan Profiles API库。您也可以自己解析配置文件JSON文件,并使用相关的Vulkan API查询设备功能以确定配置文件兼容性。

Vulkan Profiles

Android使用Vulkan Profiles,它定义了在运行Android的每个设备上可用的功能和扩展。

Android基线配置文件 (ABP) 是构建Vulkan配置文件的首次尝试。ABP2021ABP2022是向后兼容的配置文件,旨在覆盖当时>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提交流程,了解有关如何提交测试建议的分步说明。