TMG-Vulkan Pipeline Cache方案
背景
名词解释:
▪ PSO: Pipeline State Object,Vulkan用于渲染物体各种渲染状态与shader等
▪ Pipeline Cahe: Pipeline Cache,用于存储Vulkan PSO的缓存,防止新创建PSO造成卡顿
当前 Android HWUI 高度依赖 Skia 图形库用于渲染 2D 图形和文本,许多小米高端机型已采用 Skia 的 Vulkan 渲染后端。Vulkan 作为 Khronos Group 推出的低开销、跨平台图形和计算 API,对提升图形渲染效率至关重要。
在使用Skia的过程中,经常会遇到Pipeline State Object(PSO)Cache Missing和Shader Cache Missing等问题。为了解决UI渲染卡顿的问题,Apple(参考抖音 IOS 负载分析)和Flutter(参考[impeller后端](https://github.com/flutter/engine/blob/main/impeller/docs/faq.md#:~:text=why did the flutter team build impeller%3F))采用了离线编译策略。然而,Skia的设计架构允许动态生成shader,这使得离线编译并不完全适用于Skia,通常会采用预热方式来解决类似的问题。
在OpenGL ES中,大部分的sksl已经预热,而通过TMG-Skia Cache Miss 3.0方案,多个应用可以共享Shader缓存,解决了OpenGL 大部分问题。这一方案将sksl Shader转换为OpenGL的图形程序二进制,虽然有效,但并未解决Vulkan相关的缓存问题。
针对Vulkan,Pipeline Cache、Shader缓存和PSO参数需要进一步设计,以解决升级操作系统(显卡驱动)Pipeline Cache Missing的问题。Vulkan 的 Pipeline Cache 虽能存储编译后的图形管线状态,减少重复编译开销,但因其设计黑盒性,开发者无法直接控制,不能作为一级缓存直接访问。
预期收益
• 大部分系统应用首次启动由创建PSO的卡顿降为零
• 操作系统(驱动)升级后可重建Pipeline Cache,保证Pipeline Cache有效
方案设计
已有方案
• 在 Skia Cache Missing 3.0 方案中,针对 OpenGL ES 的 sksl 通过提取和缓存 Shader,在应用或系统启动时提前构建shader 二进制缓存,解决 Cache Missing 问题并减少编译延迟。但在 Skia Vulkan 实现中,虽然缓存了 Vulkan SPIR-V 与 Pipeline Cache,却因系统更新可能导致失效,需要额外处理。
针对Vulkan的改进方案
方案简介:
• 增加构建PSO描述文件,用于与SPIR-V重建PSO
• 原有skia方案SPIR-V与Pipeline Cache是一个文件,单独拆分SPIR-V与Pipeline Cache文件
◦ 避免重新编译SKIA→SPIR-V开销
◦ 多进程共享SPIR-V文件
◦ SPIR-V与PSO描述→Pipeline Cache
• 原操作系统(驱动)升级,需要人工预热PSO,优化后,仅需预热spirv与PSO参数
• 操作系统(驱动)升级或第一次启动时,解决未预热PSO导致的卡顿问题(原有方案未存储PSO参数,无法重建PSO)

在发布或升级操作系统前,反射出构建Vulkan pipeline cache的PSO的参数与Shader二进制中间文件,预置入操作系统

·在操作系统启动时,根据需要重建或更新Pipeline Cache:

分离存储
◦ SPIR-V 作为缓存:
▪ 作为跨平台、跨设备中间着色语言文件,单独存储是合理的。避免每次编译时重新生成 SPIR-V 文件,提升效率,并且大多数 SPIR-V 文件可以被多个进程共享。
▪ 每个 SPIR-V 文件使用唯一标识符(md5或sha)命名,避免重复存储。
• 把SKSL编译为SPIR-V文件
◦ 提取的场景:打开关闭相册,设置,相机,天气,大小文件夹,浏览器;负一屏,发送通知后下拉通知栏,控制栏,通知栏与控制栏相互切换,桌面来回切换,下拉搜索,后台应用滑动,锁屏与解锁,打开抖音切换小窗等,sksl文件659个
◦ 编译为SPIR-V 300 ms左右
❗ • 多进程共享,减少了每次编译时将 SKSL 转换为 SPIR-V 的时间
• 操作系统(驱动)升级后,无需重复编译
◦ PSO 参数文件:保存每个 Pipeline 的创建参数。用于在 Pipeline Cache 失效时,重建 Pipeline。
▪ 与 SPIR-V 文件相关联的着色器信息(如顶点、片段、几何着色器等)。
▪ 其他管线配置,如顶点输入布局、光栅化状态、颜色混合状态等。
◦ Pipeline Cache 文件:保存编译后的 Pipeline 状态对象。
▪ 由于 Pipeline Cache 具有黑盒性,无法通过简单的键值查询判断缓存是否失效。因此,Pipeline Cache 文件依然作为二进制文件保存,但与其他文件分开存储。
▪ 在操作系统或显卡驱动升级时,Pipeline Cache 会失效(即”Cache Missing”),此时需要通过保存的 PSO 参数和 SPIR-V 文件来重建 Pipeline。
- PSO 重建流程
a. 操作系统或显卡驱动****升级:
▪ 当操作系统或显卡驱动升级时,检查当前的 Pipeline Cache 文件是否有效。
▪ 如果 Pipeline Cache 文件失效(Cache Missing),则需要根据保存的 PSO 参数和 SPIR-V 文件重新生成管线状态。
b. 重建 PSO 的步骤:
▪ 加载 SPIR-V 文件:根据保存的 SPIR-V 文件哈希值加载对应的 SPIR-V 文件。
▪ 加载 PSO 参数文件:根据 Pipeline 的标识符加载与之对应的 PSO 参数文件。
▪ 调用 vkCreateGraphicsPipelines 重建 Pipeline:
• 使用从参数文件中加载的状态信息(如顶点输入、光栅化状态等),结合 SPIR-V 文件重新创建 Pipeline。
▪ 保存新的 Pipeline Cache:生成新的 PSO 后,将其保存到 Pipeline Cache 文件中,供下次使用。
风险
• 无
落地计划
遗留项
讨论OS3.0最终可行的方案
• 云控数据库采集新Pipeline info与Spriv是否可行
◦ 结论:OS3项目暂不采用,人力不足需云支持,下一阶段执行
• 提前提取Pipeline info与Spriv,之后实时编译pipeline cache是否可行,时间是否过长
◦ 结论:可行,时间在可控范围
◦ 采集场景:
i. 清除数据刷机后启动退出相册,设置,浏览器,相机应用,启动退出大小文件夹。
ii. 进入负一屏,滑动负一屏,退出负一屏
iii. 进入天气,滑动天气,退出天气
iv. 需要模拟发些通知
v. 下拉收起通知栏
vi. 下拉收起控制中心
vii. 负一屏还需要上下滑动
viii. 锁屏和解锁
ix. 通知栏下拉收起的特定场景:锁屏界面、抖音和王者荣耀的启动和运行过程
x. 最近任务列表的进入、滑动、退出
◦ O3上19个应用的hwui采用Vulkan
◦ 生成pipeline cache大小为5.48M

单线程编译pipeline cache,总耗时6.5s,pipeline 总数708个


多线程编译pipeline cache,总耗时2.3s

