第一次卡顿:着色器编译与缓存
同一个移植项目,平时跑得很顺,第一次看到爆炸或走进新区域却突然停一下,重走一遍又顺了。除了读取素材,这种现象还可能与着色器和图形管线的准备有关。
作者 zing · 发布于 · 来源核对
画面里的新效果,可能要先变成显卡能执行的程序
着色器是参与绘制画面的小程序,例如计算物体表面的颜色或光照。显卡驱动需要把相应代码编译成当前 GPU 能执行的形式。绘制时还要配合混合、深度测试等规则;把这些组成可用的绘制配置,也可能有准备成本。
原平台的绘制方式换到另一套图形接口和 GPU 上,不能总是原样照搬。模拟器可能要根据游戏当时使用的效果,生成适合目标设备的着色器。原生移植也可能遇到类似的首次准备工作,具体取决于引擎、图形接口和驱动的实现。
如果这些工作恰好挡在当前帧前面,画面就要等。以 60 帧每秒为例,连续两帧之间大约只有 16.7 毫秒;某一帧突然花了 60 毫秒,即使前后都很快,人也能察觉停顿。这些数字只是解释时间关系,不是某款游戏的测试结果。

缓存省去的是重复准备
第一次编译完成后,程序或驱动可以缓存准备结果。再次用到相同、仍然适用的配置,就有机会直接复用,不必重新做一遍。所以“第一次卡,第二次顺”可能是缓存开始发挥作用,并不表示第二次少画了内容。
有些项目会在启动时预编译,把等待移到游戏开始之前。另一种思路是先用已准备好的通用方案绘制,同时在后台准备更专门的版本。Dolphin 的 Ubershaders 技术文章解释了后一种做法;它是理解原理的案例,不是所有设备都应照抄的设置表。
缓存也有使用条件。换了 GPU、驱动、图形后端或相关设置,旧结果不一定还能复用;而尚未遇到的效果,也可能继续需要准备。缓存减少等待,不会替设备补上本来不足的持续绘制能力。Vulkan 官方示例就将管线创建、缓存和跨次运行复用分别说明。
卡顿的样子能提供线索,不能直接定案
新区域往往也要读取、解压地图与贴图;CPU 转译、内存不足或后台任务同样可能造成停顿。仅凭“第一次卡一下”,不能认定一定在编译着色器。
阅读移植项目的运行记录时,“平均 60 帧”与“首次出现新效果仍有停顿”可以同时成立。若记录能说明是否首次运行、缓存是否保留、使用了哪个图形后端,就比单独一个平均帧率更能说明体验。持续低帧率与偶发长帧,需要分别解释。