锁屏可变字体玻璃方案设计

一、控件(圆角矩形)玻璃算法

以菲涅耳方程为基础,手机上的折射模型建模为一个Background(壁纸、桌面),控件建模为有一定厚度的,边缘为圆角的模型,切与Background没有缝隙。

Snell’s Law / 2D折射模型:

算法可视化流程,OS4玻璃shader功能多,主要包括折射、反射、Bloom、混色、对比度亮度调整、高光边。

白板流程图:OS4玻璃shader算法可视化 SDF → Normal → Refraction → Reflection → Blend → 应用亮度曲线调整/应用饱和度和亮度调整 → bloom → 混色 → 内边缘效果 → 光照

优化结果:

圆角矩形大小:1000 x 500

机型:O3

优化版本\频点222频点443频点734频点832频点补丁版本
基线1200 us601 us370 us327 usPatch 1
版本v0.2849 us425 us257 us227 usPatch 7
版本v0.3740 us372 us225 us199 usPatch 11
版本v0.4640 us322 us196 us172 usPatch 15
版本v0.5669 us337 us204 us179 usPatch 18
版本v0.6333 us170 us107 us94 usPatch 35

与Apple的耗时对比:

MIApple
场景:控制中心 28个控件
GPU耗时增加0.48 ms3.47 ms

二、锁屏可变字体玻璃方案

锁屏字体玻璃渲染流程:

白板流程图:锁屏字体玻璃渲染流程 上层输入可变字体的PATH → 字体SDF生成 → 根据SDF生成法线 → 容器截图(模糊半径46) → 容器截图(模糊半径500) → 玻璃shader上屏

与控件(圆角矩形)玻璃相比,锁屏字体玻璃难点更大,有以下几个方面的原因:

  • 异形SDF的计算复杂度高
  • Shader复杂,集成难点大
  • 性能功耗挑战大,优化难度高

2.1 异形SDF的计算

锁屏字体是可变字体,由三阶贝塞尔曲线表示,在CPU上把曲线细分为线段:

然后上传GPU进行光栅化,共6个Draw Call: 1)Path Distance I;2)Path Interior I;3)Accumulator I;4)Path Distance II;5)Path Interior II;6)Accumulator II。前三个Draw Call和后三个Draw Call shader几乎一样,区别是反走样参数设置的不一样。详细算法原理参考《字体SDF生成算法原理》

白板流程图:SDF生成Draw Call流程 三阶贝塞尔曲线 →(CPU) 细分为线段上传GPU →(到轮廓到最小距离) path distance → path interior →(winding number计算) accumulator →(SDF) path distance II → path interior II → accumulator II

该算法是架构技术部竟分苹果的结果,我把metal实现用AI转成Vulkan实现,集成系统后,一个View的GPU耗时1.05ms,两个View GPU耗时2.1ms,很难满足落地需求。

我对算法进行了改造:

白板流程图:改造后的SDF渲染方案 View(任意大小) → CPU上转成线段表示 → GPU NDC坐标(x:[-1,1], y:[-1,1]) → 固定大小渲染(400x400) → 拉伸到和原始View同样大小

这样两个View,14个Draw Call的GPU耗时降低到0.5ms左右,用小分辨率的SDF不影响玻璃的渲染效果。

2.2 SDF渲染管线的集成

每个Draw Call都需要vertex和fragment shader,当前2D引擎SKIA对vertex shader支持的不好,需实现自定义OP来集成,集成难点大。

2.3 渲染线程优化方案

渲染线程在每帧render的时候都重新录制命令,导致cpu负载重。

主要的变量有:1)可变字体的三阶贝塞尔曲线每帧都变,每帧更新不可避免;2)每个shader的push constant数据和贝塞尔曲线相关,因此每帧都变;3)index/instance个数随贝塞尔线段的个数有关。第一个变量每帧都要更新不可避免,第二、第三个变量需要利用GPU Driven的计算来降低CPU的负载:

优化后CPU提交耗时由870us降低到68us。

优化前 / 优化后:

三、CPU指令与竞品对比

平均单帧优于荣耀70%。

场景算力平均占比算力峰值占比平均单帧最大单帧
新功能 下拉通知栏2.9%16.2%10,587,10046,657,524
线上 下拉通知栏2.90%8.80%10,544,99951,068,860
线上多xx%0.4%-8.6%
新功能 亮灭屏2.9%20.8%11,079,16342,082,026
线上 亮灭屏2.6%38.2%9,195,45365,133,713
线上多xx%20.8%(最新已优化到了15%)-35%
新功能锁屏堆叠滑动3.927.30%12,229,12745,620,406
荣耀gt pro 锁屏通知堆叠滑动11.9%23.9%40,984,182113,724,397
-70%-60%

平均单帧差于线上20%

  1. 47% - 可变字体平均单帧增加0.7M负载,其中0.5M从字体库读取可变字体;
  2. 20% - 玻璃平均单帧增加0.3M负载,主要由数据更新及Draw Call提交导致的;
  3. 33% - 高级材质引起的__epoll_pwait,0.5M负载 —— 有优化方案,优化后只剩0.1M。

共计1.5M负载

四、功耗

时钟玻璃功耗增加65mA, 其中CPU增加5mA,GPU增加50mA,不超过40mA。

五、效果

六、下一步优化方向

SDF DC由6个减少为3个。