Flutter 新一代图形渲染器 Impeller

Flutter在2022年的Roadmap中提出需要重新考虑着色器的使用方式,计划重写图像渲染后端。最近该渲染后端 Impeller(叶轮)初见端倪,本文将介绍 Impeller 解决的问题、目标、架构和渲染细节。

背景

Flutter在过去一年多时间解决了很多Jank问题,但着色器编译导致的Jank问题一直没有彻底解决。这里我们先了解下什么着色器编译Jank。Flutter底层使用了skia做为2D图形渲染库,而skia内部定义了一套SkSL(Skia shading language),SkSL 属于 GLSL 变体。在Flutter的光栅化阶段,当第一次使用着色器时Skia会根据绘图命令和设备参数生成 SkSL,然后再将 SkSL 转换为特定后端(GLSL、GLSL ES 或 Metal SL)着色器,并在设备上编译为着色器程序。而编译着色器可能花费几百毫秒,导致数十帧的丢失。定位着色器编译Jank问题可以查看trace信息是否有 GrGLProgramBuilder::finalize 调用。

Flutter为了解决该问题,在Flutter 1.20 版本中为GL后端实现了SkSL预热机制,支持离线收集应用程序中使用的 SkSL 着色器并保存为json文件,然后把该文件打包到应用程序中,最终用户首次打开应用程序时预编译 SkSL着色器,从而减少着色器编译 jank。随后,在 Flutter 2.5中支持了 iOS metal 着色器的预编译。

Flutter gallery应用预热前后,在Moto G4上从90ms减少到40ms,在iPhone 4s上从300ms减少到80ms,性能提升很明显。

在Flutter官方提供了SkSL着色器预热后,社区经常提到的一些高频问题收集如下:

Q1. 为什么不预编译用到的所有着色器?

为了获得最佳性能,Skia GPU backend在运行时会根据一些参数(如绘图命令,设备型号等)动态生成着色器。这些参数的组合会生成大量的着色器,无法在应用程序中预编译和内置。

Q2. 不同设备上捕获的 SkSL shader 通用吗? 理论上,没有机制保证在一台设备上捕获的 SkSL shader 在其他设备上也有效。实际上,(有限的)测试表明 SkSL shader 能表现的较好,即使在iOS上捕获的 SkSL 应用到Android设备,或者模拟器上捕获的SkSL应用到真机上。

Q3. 为什么不创建一个超级着色器并仅编译一次?

这样的着色器会非常大,本质上是重新实现 Skia GPU 功能。大shader需要更长的编译时间,从而引入更多的 Jank。

但SkSL着色器预热也存在自身的缺点和局限性:

1.应用包体积变大
2.应用启动时间变长,因为需要预编译 SkSL shader
3.开发体验不友好
4.SkSL shader 的通用性无保证且不可预测

以下时间线列举了Flutter在解决Jank问题上的努力和进展:

对于着色器编译Jank问题,官方经过多次尝试依然无法彻底解决,因此在2022年的roadmap中请明确提出要重新考虑使用着色器的方式,计划重写图像渲染后端。在2022年计划在iOS上将 Flutter 迁移到新架构上,然后根据经验将该解决方案移植到其他平台上。最近,该图形渲染后端 impeller(叶轮) 初见端倪,接下来让我们看看 impeller有什么独特之处。

Impeller架构

Impeller是为flutter量身定做的渲染器,目前处于早起原型阶段,仅实现了metal后端,支持iOS和Mac系统。工程方面,他依赖了 flutter fml 和 display list,并实现了display list dispatcher 接口,可以容易的替换skia。Impeller被flutter flow子系统所使用,因此得名。

Impeller核心目标:

1.可预测的性能:在编译时离线编译所有着色器,并根据着色器预先构建 pipeline state objects。
2.可检测:所有的图形资源(textures、buffers、pipeline state对象等)都被追踪和标记。动画可以被捕获并持久化到磁盘而不影响渲染性能。
3.可移植:没有与特定的渲染API相绑定,着色器编写一次并在需要时转换。
4.使用现代图形API:大量使用(但不依赖)现代图形API(如Metal和Vulkan)的特性。
5.有效利用并发性:可以在多线程上分发单帧工作负载。

impeller软件架构

impeller大致可以分为Compiler、Renderer,Entity、Aiks以及基础库Geomety和Base等几个模块。

1.Compiler: host端工具,包含着色器 Compiler 和 Reflector。Compiler用于把 GLSL 4.60 着色器源码离线编译为特定后端的着色器(如MSL)。Reflector 根据着色器离线生成 C++ shader bindings,以在运行时快速构建pipeline state objects (PSO)
2.Renderer: 用于创建buffer、从shader bindings生成pipeline state objects、设置RenderPass、管理uniform-buffers、细

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值