Android NDK开发详解RenderScript之从 RenderScript 迁移


从 Android 12 开始,RenderScript API 已被废弃。它们将继续正常运行一段时间,但设备和组件制造商已停止提供硬件加速支持,并将在未来的版本中完全取消对 RenderScript 的支持。

许多用户会发现 C/C++ 性能足以满足他们的需要。如果您仅将 RenderScript 用于内建函数,可使用 RenderScript 内建函数替换工具包来替代。后者更易于使用,并且有可能将性能提高 2 倍!

如果您确实需要充分利用 GPU 加速功能,我们建议您将脚本迁移到 Vulkan。

在 Android 平台中废弃 RenderScript 后,我们还将在 Android Gradle 插件中取消对 RenderScript 的支持。从 Android Gradle 插件 7.2 开始,废弃了 RenderScript API。它们将继续正常运行,但会调用警告,并将在未来的 AGP 版本中彻底移除。本指南介绍了如何从 RenderScript 迁移。

从内建函数迁移

尽管 RenderScript 内建函数在 RenderScript 废弃后将继续正常运行,但它们只能针对 CPU(而非 GPU)执行。

如果您的应用使用了内建函数,您就可以使用独立的替换库;我们的测试表明,其速度比使用现有 RenderScript CPU 实现更快。

该工具包包含以下函数:

混合函数 (blend)
模糊处理函数 (blur)
颜色矩阵函数 (colorMatrix)
卷积函数 (convolve)
直方图函数 (histogram) 和 histogramDot
对照表函数 (lut) 和 lut3d
大小调整函数 (resize)
将 YUV 转换为 RGB 的函数 (yuvToRgb)
如需了解完整详情和限制条件,请参阅该工具包的 README.md 和 Toolkit.kt 文件。

如需下载、添加和使用该库,请执行以下步骤:

从 GitHub 下载相应项目。

找到并构建 renderscript-toolkit module。

注意:如果您希望改为针对 GPU 运行内建函数,请参阅从脚本迁移中所述的使用 Vulkan 对模糊处理和颜色矩阵进行编码的示例。
通过修改应用的 build.gradle 文件,将该库添加到您的 Android Studio 项目中。

调用该工具包的相应方法。

示例:从 ScriptIntrinsicBlur 函数迁移

如需替换 ScriptIntrinsicBlur 函数,请执行以下操作:

如需对位图进行模糊处理,请调用 Toolkit.blur。

var blurredBitmap = Toolkit.blur(myBitmap, radius)

如果您需要对由字节数组表示的图片进行模糊处理,请指定宽度、高度和每像素字节数。


val outArray = Toolkit.blur(inputArray, bytesPerPixel, width, height, radius)

注意:由于该库会不断完善,请参阅相应工具包文档以获取最新指南。
如果以 Android 12(API 级别 31)及更高版本为目标平台,请考虑使用 RenderEffect 类(而非 Toolkit.blur())。

从脚本迁移

如果 RenderScript 内建函数替换工具包(与 RenderScript 相比,性能可能提升 2 倍)不适用于您的应用场景,建议您将 RenderScript 脚本迁移到跨平台 Vulkan API。不过,在大多数设备上,脚本已经是在 CPU(而非 GPU)上运行,因此似乎没有必要进行迁移。在某些用例中,C/C++ 的计算速度可能比 RenderScript 或 Vulkan 更快;即便 Vulkan 或 RenderScript 可以提供更好的性能,C/C++ 的速度也足够快了。

为了更好地了解如何迁移功能,请查看示例应用。该示例演示了如何使用 RenderScript 对位图进行模糊处理并执行颜色矩阵转换,以及如何使用 Vulkan 编写等效的代码。

如果您的应用需要支持一系列版本,请为搭载 Android 6(API 级别 23)及更低版本的设备使用 RenderScript,为 Android 7(API 级别 24)及更高版本使用 Vulkan。如果您的 minSdkVersion 为 24 或更高版本,则无需使用 RenderScript;Vulkan 可用于您支持的每台设备。

Vulkan 不提供 Kotlin API 和 Java API,因此不存在从 RenderScript 到 Vulkan 的直接映射。如需通过 Kotlin 或 Java 访问此代码,您需要使用 NDK 编写 Vulkan 代码,并创建 JNI 函数。

以下几部分介绍了从 RenderScript 迁移的各个方面。示例应用几乎涵盖了上述所有考虑因素。为了更好地理解这些因素,请对比以下 RenderScript 和 Vulkan 等效代码。

初始化

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

创建一个 Vulkan 实例。

选择支持计算队列的 Vulkan 实体设备。

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

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

示例应用演示了如何在 VulkanContext.h 中初始化 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 规范中的资源创建和资源描述符部分。

脚本

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

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

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

注意:与 RenderScript 脚本不同,GLSL 着色器脚本不能包含任何可调用函数,并且只能有一个内核。
调整脚本全局变量
根据脚本全局变量的特性,我们建议对未在着色器中修改的全局变量使用特化常量、推送常量或统一缓冲区对象:

特化常量:建议用于在不同内核调用中基本一致的脚本全局变量。更改特化常量的值需要重新创建计算流水线。
推送常量:建议用于频繁更改且小于 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 规范中的命令缓冲区和内存屏障部分。

本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。

最后更新时间 (UTC):2023-02-26。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五一编程

程序之路有我与你同行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值