对于非常适合使用 GPU 计算的工作负载,将 RenderScript 脚本迁移到 Vulkan 计算,有助于应用更直接地控制 GPU 硬件,从而有望释放比其他 API 更多的性能。
下面简要介绍了相关内容,旨在帮助您使用 Vulkan 计算着色器替换 RenderScript 脚本。
Vulkan 初始化
通过执行以下步骤,使用 NDK 创建 Vulkan 上下文,而不要使用 Kotlin 或 Java 创建 RenderScript 上下文对象。
创建一个 Vulkan 实例。
选择支持计算队列的 Vulkan 实体设��。
创建一个 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 计算流水线:
- 使用已编译的 SPIR-V 着色器创建一个着色器模块。
- 创建一个用于指定资源绑定的描述符集布局(如需了解详情,请参阅分配)。
- 通过描述符集布局创建描述符集。
- 通过描述符集布局创建流水线布局。
- 使用着色器模块和流水线布局创建计算流水线。
如需了解详情,请参阅 Vulkan 规范中的计算流水线部分。
启动计算
如需使用计算流水线启动计算,请执行以下操作:
- 使用 Vulkan 资源更新描述符集。
- 创建一个 Vulkan 命令缓冲区,并记录以下命令:
- 绑定流水线和描述符集。
- 分派计算工作组。
- 将命令缓冲区提交到计算队列。
- 在队列中等待,也可以选择性地返回同步栅栏。
如需将多个内核链接在一起(例如,如需使用 ScriptGroup 迁移代码),请将它们记录在单个命令缓冲区中,并与内存屏障进行同步。
示例应用演示了两项计算任务:
- HUE 旋转:一个具有单个计算着色器的简单计算任务。如需查看代码示例,请参阅
ImageProcessor::rotateHue。 - 模糊处理:一个按顺序执行两个计算着色器的更复杂的计算任务。如需查看代码示例,请参阅
ImageProcessor::blur。
如需详细了解命令缓冲区或内存屏障,请参阅 Vulkan 规范中的命令缓冲区和内存屏障部分。