编程学习札记

首屏编译了 144 个着色器程序,其实只用得到 39 个

2026-10-23

先数清楚

小游戏启动慢,我先在诊断版里加了一种日志:每编译一个着色器程序就输出一行。统计下来,光首页就编译了 144 个程序,可实际画到屏幕上的只有一小部分。

为什么会多编译

Godot 4 的 GLES3 后端第一次绑定某个着色器时,如果手上没有程序缓存,就会按默认的特化掩码,把这个着色器的全部变体都编译一遍。桌面和移动端有缓存可用,第二次启动就快了;WebGL 上始终没有这种缓存,所以每次启动都要全部重来,而其中大部分变体根本不会被用到。

这件事在项目代码里绕不开,只能改引擎。

先能原样构建,再打补丁

要改引擎,前提是能从源码构建出和原来用的模板一模一样的东西,否则出了问题分不清是补丁的锅还是构建的锅。步骤是:

  1. 找到模板对应的引擎提交,锁定工具链:Emscripten 4.0.10、SCons 4.9.1。
  2. 不打任何补丁,先构建一次,和原模板逐项对比:胶水 JS 只差换行符(原模板是在 Windows 上构建的);wasm 各段的函数数、导入、导出完全相同;模拟器里首页编译的 144 个程序,集合也一致。
  3. 这时再加上补丁:没有程序缓存时,只编译实际请求到的那个变体。

结果:首页需要编译的程序从 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

← 返回目录