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文件

◦ 避免重新编译SKIASPIR-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。

  1. 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