将脚本迁移到 Vulkan

对于非常适合使用 GPU 计算的工作负载,将 RenderScript 脚本迁移到 Vulkan 计算,有助于应用更直接地控制 GPU 硬件,从而有望释放比其他 API 更多的性能。

下面简要介绍了相关内容,旨在帮助您使用 Vulkan 计算着色器替换 RenderScript 脚本。

Vulkan 初始化

通过执行以下步骤,使用 NDK 创建 Vulkan 上下文,而不要使用 Kotlin 或 Java 创建 RenderScript 上下文对象。

  1. 创建一个 Vulkan 实例。

  2. 选择支持计算队列的 Vulkan 实体设��。

  3. 创建一个 Vulkan 逻辑设备并获取计算队列。

(可选)您可以在 Android 上设置 Vulkan 验证层,以加速 Vulkan 应用开发。

示例应用演示了如何在 VulkanContext.h 中初始化 Vulkan 上下文。如需了解详情,请参阅 Vulkan 规范中的初始化以及设备和队列部分。

Vulkan 分配

RenderScript 分配可以迁移到 Vulkan 存储映像或 Vulkan 存储缓冲区。为了提升只读图片的性能,请通过提取操作使用示例图片,要么将其用作组合图片采样器,要么将其与独特的采样器和采样图片绑定结合使用。

Vulkan 资源在 Vulkan 中分配。为避免在与其他 Android 组件交互时产生内存复制开销,请考虑使用 VK_ANDROID_external_memory_android_hardware_buffer 扩展程序将 Android AHardwareBuffer 导入到 Vulkan 中。此扩展程序适用于所有支持 Vulkan 1.1 的 Android 设备。如需了解详情,请参阅 FEATURE_VULKAN_HARDWARE_VERSION。

示例应用演示了如何在 VulkanResources.h 中创建 Vulkan 资源。如需了解详情,请参阅 Vulkan 规范中的资源创建和资源描述符部分。

转换为 Vulkan 计算着色器

您的 RenderScript 脚本必须转换为 Vulkan 计算着色器。您可能还需要根据 RenderScript 全局变量的用法调整代码。

编写 Vulkan 计算着色器

Vulkan 计算着色器通常采用 OpenGL 着色语言 (GLSL) 编写,然后编译为标准便携式中间表示 (SPIR-V) 格式。

如需详细了解如何将着色器集成到您的应用中,请参阅 Android 上的 Vulkan 着色器编译器。

调整脚本全局变量

根据脚本全局变量的特性,我们建议对未在着色器中修改的全局变量使用特化常量、推送常量或统一缓冲区对象:

  • 特化常量:建议用于在不同内核调用中基本一致的脚本全局变量。更改特化常量的值需要重新创建计算流��线。
  • 推送常量:建议用于频繁更改且小于 maxPushConstantsSize(保证的最低大小:128 字节)的脚本全局变量。
  • 统一缓冲区:建议用于频繁更改且大于推送常量上限的脚本全局变量。

对于着色器中发生变化的全局变量,���可以使用 Vulkan 存储映像或 Vulkan 存储缓冲区。

计算

您需要创建 Vulkan 计算流水线,目的是让 GPU 执行计算着色器。

创建 Vulkan 计算流水线

示例应用中的 ComputePipeline.h 文件演示了如何创建 Vulkan 计算流水线。

如需在 Vulkan 中使用已编译的 SPIR-V 着色器,请按如下步骤构建 Vulkan 计算流水线:

  1. 使用已编译的 SPIR-V 着色器创建一个着色器模块。
  2. 创建一个用于指定资源绑定的描述符集布局(如需了解详情,请参阅分配)。
  3. 通过描述符集布局创建描述符集。
  4. 通过描述符集布局创建流水线布局。
  5. 使用着色器模块和流水线布局创建计算流水线。

如需了解详情,请参阅 Vulkan 规范中的计算流水线部分。

启动计算

如需使用计算流水线启动计算,请执行以下操作:

  1. 使用 Vulkan 资源更新描述符集。
  2. 创建一个 Vulkan 命令缓冲区,并记录以下命令:
    1. 绑定流水线和描述符集。
    2. 分派计算工作组。
  3. 将命令缓冲区提交到计算队列。
  4. 在队列中等待,也可以选择性地返回同步栅栏。

如需将多个内核链接在一起(例如,如需使用 ScriptGroup 迁移代码),请将它们记录在单个命令缓冲区中,并与内存屏障进行同步。

示例应用演示了两项计算任务:

  • HUE 旋转:一个具有单个计算着色器的简单计算任务。如需查看代码示例,请参阅 ImageProcessor::rotateHue。
  • 模糊处理:一个按顺序执行两个计算着色器的更复杂的计算任务。如需查看代码示例,请参阅 ImageProcessor::blur。

如需详细了解命令缓冲区或内存屏障,请参阅 Vulkan 规范中的命令缓冲区和内存屏障部分。