TGFX-跨平台 2D 绘图引擎
1、项目简介
TGFX(Tencent Graphics) 是一个跨平台的纯 GPU 绘图引擎,提供了完备的图片,矢量和文本的 2D 绘制能力,目前已支持:iOS, Android, macOS, Windows, Linux, 以及 Web 等平台。它最初是从 PAG 动效开源项目中孵化而来,作为谷歌 Skia 绘图引擎的轻量化替代方案,以仅 400K 左右的包体大小实现了 Skia 近2M 包体的绝大部分功能,并为 PAG 4.0 版本带来了约 65% 的包体降低以及 60% 的矢量渲染性能提升。截止 2023 年 10月,借助 PAG 项目,TGFX 已经实际运行在了1500+ 的头部业务场景中,如微信,手Q,王者荣耀,小红书,知乎,Bilibili等,稳定性也经过了 10 亿+ 用户设备的持续验证。除了 PAG 外,TGFX 目前也独立在部分音视频编辑框架,Hippy动态化框架以及腾讯文档中作为底层的绘图引擎使用。
PAG 动效:https://github.com/Tencent/libpag
Hippy动态化框架:https://github.com/Tencent/Hippy
2、诞生背景
谷歌的 Skia 是一个非常优秀的 2D 绘图引擎,目前依然是行业里在绘图引擎领域的事实标杆。但 Skia 主要还是服务于谷歌系产品相关的常见诉求,对于其他产品的特殊需求场景可能难以完全覆盖。例如我们在 PAG 动效项目里就存在极致的包体精简,以及对可预测的时间轴渲染进一步优化的诉求。行业里目前也缺少性能与 Skia 匹配但更加轻量的其他解决方案。为了继续突破包体和性能的限制,我们从 2021 年开始投入研发了一套轻量的纯 GPU 绘图引擎 TGFX,最终以 400K 左右的包体完成了对 Skia 的轻量化替代,并带来了 PAG 4.0 版本矢量渲染性能 60% 的提升,腾讯文档在接入使用后也获得了约 50% 的内存占用降低。接下来我们会以这个精简的版本为基础持续完善,争取为行业补充 Skia 之外的另一个轻量化选项。
3、架构设计
包体优化
TGFX 最终以 400K 左右的大小覆盖了 Skia 近 2M 包体的绝大部分功能。
核心优化策略主要有两点:
● 彻底抛弃传统的 CPU 渲染管线:现代的硬件已经几乎不存在没有 GPU 的设备,即使像服务器端这种特殊的场景,通过 Swiftshader 来模拟 GPU 也可以得到很不错的性能。但 Skia 由于历史原因一直同时包含了 CPU 和 GPU 的两条渲染管线,并且由于它的 GPU 渲染管线重度依赖 CPU 的部分,导致没法单独使用它的 GPU 渲染管线。我们在 TGFX 中彻底解决了这个耦合的问题,打造出了一个纯 GPU 的绘图引擎,这里就节省了大概一半的包体。
● 最大化的利用平台端内置的所有能力:例如图片解码,字体解析,矢量栅格化等等,这些都会优先使用系统原生的接口替代内置第三方库的策略。以文本和矢量的栅格化为例,在 iOS 上我们直接使用了系统提供的 CoreGraphics,文本方面则利用起 CoreText 等。而在其他平台才嵌入了 Freetype。虽然增加了不同平台适配的工作量,但是包体确实也获得了极致的优化。
调度优化
TGFX 并不只是做 Skia 的简化,还把一些在业务上调用起来非常复杂的通用性流程进行了抽象封装:
Skia 虽然提供了 GPU 的渲染管线,但只实现了跨平台渲染的部分,所有跟平台相关的视图桥接以及上下文的初始化都需要用户自己处理。这会导致用户正常用起来 Skia 的 GPU 模式需要对每个平台写大量的适配代码。除了工作量大外这部分还是兼容性的重灾区,要处理很多类似 iOS 中退到后台执行 OpenGL 的特殊情况,以及线程安全问题。
为了避免每个业务都要重新经历一遍这些兼容性问题和坑点,我们在设计 TGFX 的调用流程时,在头尾补充上了 Skia 没有的 Device & Window 系统,并把在各个平台积累的GPU适配经验都沉淀到了这个模块中:
借助TGFX 提供的 Device & Window 系统,业务只要按照统一的模式进行调用,所有平台相关的复杂度都可以不用关心,并且从 API 上限制了你必须以线程安全的方式进行调用。即使没有非常资深的 GPU 渲染经验也可以很轻松上手使用。
其他优化
在性能和架构方面,还做了这些额外的优化:
● 默认开启了 HardwareBuffer 的支持,来全面加速纹理的提交,包括 Android 端。
● 暴露了引擎内部 Path 对应的 GPU 高速缓存,避免矢量绘制充分进行三角剖分操作。
● GPU 对象支持在任意线程释放,等关联的上下文激活时才清理,避免随机 Crash 问题。
● 约束图片解码完会尽可能只缓存 GPU 的纹理部分,理论上全局可以降低一半的内存占用。
● 将绝大部分缓存都交给了上层业务精确管理,避免随机绘制的缓存持续占用额外的内存。
● 在全平台都实现了默认字体的读取能力,包括浏览器,避免下载上百兆 CJK 字体的压力。
● 增加了对各种硬解视频帧格式的直接绘制能力,可以一次性上屏无需通过 CPU 转换格式。
● 放弃了 SKSL 的统一 Shader 语言设计,更加符合原生接口调用习惯,既节省了包体,也减少了 GPU Program 的编译耗时。
4、项目规划
TGFX 项目未来的部分规划:
● 全面的指令化渲染,最大化并发准备 GPU 数据。
● Vulkan 和 Metal 等渲染后端的支持。
● Picture 回放类的支持。
● 全链路广色域渲染支持。
● 打印支持,支持渲染输出 PDF。
● 3D 矩阵变换能力从 PAG 下沉到 TGFX。
● 完善的运行时性能数据统计和调试接口。
5、项目地址
https://github.com/Tencent/tgfx