5 分钟带你看懂 GCanvas 渲染引擎的演进 (二)

阅读数:3 2019 年 12 月 17 日 14:11

5分钟带你看懂 GCanvas渲染引擎的演进(二)

架构演进与优化

以业务先赢的基本原则,保证业务的前提下,架构容器和升级变化过程中,GCanvas 引擎也经历了演进和升级优化。

2017 年的架构
以插件为主的实现,仅支持移动端

5分钟带你看懂 GCanvas渲染引擎的演进(二)

最新架构
提供标准接口,链路升级,API 升级,不仅支持移动端还支持服务端

5分钟带你看懂 GCanvas渲染引擎的演进(二)
架构变化主要有以下几个方面:

  • 适配支持更多的 JS 框架和库
  • JS 到 Native 调用通路,从模块路由反射升级到 JSBinding
  • 渲染 API 支持 Metal
  • 增加 MacOS 和 Linux 平台支持

► 内功修炼

在快速迭代过重中,保持修炼内功。为保证高性能这个根本,在链路、内核以及底层图形 API 等方面也都做了不少优化与升级。

JS 到 Native 链路优化

从 Weex 调用链路到 JSBinding,Weex 容器的 JS 到 Native 的通路采用模块路由和反射的调用方式调用具体的模块和组件。在 UI 和一些非高频的场景完全能满足需求。

但是对于连续操作、连续动画等高频的 JS 到 Native 通讯的场景,链路上的耗时非常大,导致卡顿产生。这也是为什会 BindingX 和 GCanvas 的 JSBinding 的出现。

BindingX 是另一种解决频发通讯消耗的方案,有兴趣的可以看下 BindingX。(地址戳阅读原文)

GCanvas 的 JSBinding 的实现:通过链路调用的改造,整体帧率平均提升 10 帧左右。Android 和 iOS 的 JSBinding 实现方案类似。

以 iOS 举例说明:iOS 尝试使用 JSExport 和全局方法,两种 JSBinding 方案。

  • 第一种方案,使用 JSExport 和 JSExportAS
复制代码
@import JavaScriptCore;
@protocol TestObjecJSExport <JSExport>
JSExportAs(foo, - (void)foo:(NSString *)msg);
@end

第二种方案,使用 C Export 将方法和属性用 JSStaticFunction 和 JSStaticValue 进行绑定

复制代码
// 方法 JSStaticFunction
typedef struct {
const char* name; // 方法名
JSObjectCallAsFunctionCallback callAsFunction; //Native 方法实现
JSPropertyAttributes attributes; // 方法设置
} JSStaticFunction;
// 属性 JSStaticValue
typedef struct {
const char* name; // 属性名
JSObjectGetPropertyCallback getProperty; //Native 属性 Getter 实现
JSObjectSetPropertyCallback setProperty; //Native 属性 Setter 实现
JSPropertyAttributes attributes; // 属性的读写设置
} JSStaticValue;

两种实现方案,经过测试对比第二种方案在性能更好。原因在于静态 JS 方法是通过方法名到 Native 函数的直接映射,而 JSExport 的方案则需要类型检查,协议校验,再调用 Native 方法中间经过额外的处理。

简单的耗时测试数据对比:
5分钟带你看懂 GCanvas渲染引擎的演进(二)

JS 到 Native 数据传输
方法调用与属性访问之外,参数数据的传输也影响每帧耗时,尤其是在 WebGL 的场景,通常有很大顶 点数据需要处理,有几万 - 几十万字节,甚至更多。JS 到 Native 的大数据传输避免内存拷贝。

JS 与 Native 对象生命周期
JSBinding 的对象生命周期管理,JS 对象与 Native 对象一一对应,在 JS 对象创建触发 JSObjectInitializeCallback 回调,创建 Native 对象,并将 JS 与 Native 建立关联。JS 的 GC 回收对象触发 JSObjectFinalizeCallback 的回调中去释放对应 Native 对象。

帧率优化
除了调用链路对帧率的提升,单帧绘制的 CPU 和 GPU 耗时相关的优化点

  • 顶点数据计算,顶点数据合并提交
  • 优化缓存策略,优化文字相关纹理的缓存
  • 增加状态管理,减少 GPU 提交数据和频次
  • 优化多边形填充效率
  • 抗锯齿等耗时特性可选

w3c 标准完善

  • 支持阴影
  • 支持虚线
  • 支持多 Clip 区域嵌套
  • 支持 Winding Rule 支持

扩展能力,扩展一些非标接口支持 Sketch 渲染,

  • 阴影的扩散
  • 路径的图案填充
  • 路径的高斯模糊
  • 路径的内描边和外描边

底层图形 API 升级
在 iOS12 之后,苹果将 OpenGL ES API 设为废弃,在已支持的设备上 OpenGL ES 的调用都已映射到 Metal 相应的后端实现,Metal 替换 OpenGL 势在必行。GCanvas 也已投入开发 Metal,可选择使用 Metal 作为渲染的后端。已完成了 2D 的绝大部分能力。

选择 Metal 会带来以下方面的收益:

  • 内存数据使用更高效,内存数据可共享,
  • 尽可能的榨取更多 GPU 性能
  • 摆脱 OpenGL 的状态机,更友好的面向对象编程
  • 苹果后续的持续投入和更新
  • 丰富的调试工具,能精确到每个顶点数据和每个素点颜色
  • 便捷调试这着色器语言 (Metal Shader Language)

在内核升级优化的过程中,也有很多同学积极参与其中来在此表示感谢。

稳定性

增加了 API 的自动化测试以及 CI 建立保障稳定性。

未来的方向

GCanvas 开源社区加大投入增加社区影响力, 请大家积极关注并 star
更多纹理压缩格式的支持
Vulkan 的持续演进
更多平台的支持,IoT 设备上应用
与云端渲染的融合,提供 Fass 能力
WebGPU 以及 GPU 计算方向探索
WebAssembly 的应用

本文转载自淘系技术公众号。

原文链接: https://mp.weixin.qq.com/s/8NafSk2Yfl1eCEDNBeYy1g

评论

发布