首屏编译了 144 个着色器程序,其实只用得到 39 个
先数清楚
小游戏启动慢,我先在诊断版里加了一种日志:每编译一个着色器程序就输出一行。统计下来,光首页就编译了 144 个程序,可实际画到屏幕上的只有一小部分。
为什么会多编译
Godot 4 的 GLES3 后端第一次绑定某个着色器时,如果手上没有程序缓存,就会按默认的特化掩码,把这个着色器的全部变体都编译一遍。桌面和移动端有缓存可用,第二次启动就快了;WebGL 上始终没有这种缓存,所以每次启动都要全部重来,而其中大部分变体根本不会被用到。
这件事在项目代码里绕不开,只能改引擎。
先能原样构建,再打补丁
要改引擎,前提是能从源码构建出和原来用的模板一模一样的东西,否则出了问题分不清是补丁的锅还是构建的锅。步骤是:
- 找到模板对应的引擎提交,锁定工具链:Emscripten 4.0.10、SCons 4.9.1。
- 不打任何补丁,先构建一次,和原模板逐项对比:胶水 JS 只差换行符(原模板是在 Windows 上构建的);wasm 各段的函数数、导入、导出完全相同;模拟器里首页编译的 144 个程序,集合也一致。
- 这时再加上补丁:没有程序缓存时,只编译实际请求到的那个变体。
结果:首页需要编译的程序从 144 个降到 39 个,画面不变。补丁只改了 drivers/gles3/shader_gles3.cpp 一个文件,以后跟上游合并时冲突的地方很少。
构建开销
| 项目 | 耗时 / 大小(M4 Mac mini) |
|---|---|
| 全量构建 | 约 11 分钟 |
| 只改补丁的增量构建 | 约 5.5 分钟(几乎都花在链接上) |
| brotli 压缩 wasm | 约 85 秒 |
| 工作目录 | emsdk 1.6 GB + 源码 0.45 GB + 产物约 0.7 GB |