参考案例

本质为图形 API 语义不匹配,GPU侧会发生什么取决于 图形 API、驱动容错。 可能的表现: 没有任何表现,一切正常 GPU Bound,Clocks爆炸,表现为游戏几乎卡死,几秒钟动一次 GPU重启或进程被杀掉 参考案例 大地图缩放卡死 切换画质卡死 问题本质 专属阴影的贴图没有设置(这是一张GlobalTexture,Shader侧按阴影贴图的流程进行采样)。 当玩家的城池不在太空城周围时…


本质为图形 API 语义不匹配,GPU侧会发生什么取决于 图形 API、驱动容错。

可能的表现:

  • 没有任何表现,一切正常

  • GPU Bound,Clocks爆炸,表现为游戏几乎卡死,几秒钟动一次

  • GPU重启或进程被杀掉

参考案例

大地图缩放卡死

切换画质卡死

问题本质

专属阴影的贴图没有设置(这是一张GlobalTexture,Shader侧按阴影贴图的流程进行采样)。

当玩家的城池不在太空城周围时,这个时候进入游戏,专属阴影的贴图是没有绑定的,此时直接将镜头拉高到L3的级别,会触发三谋的ShadowCache,此时所有的ShadowMapPass将不工作。这时候如果将镜头移动到可以看到太空城的位置,触发太空城的渲染流程时,专属阴影的绑定仍然为空,Unity会为空绑定添加一张默认贴图(RGBA8)。由于专属阴影是一张阴影贴图和Unity的默认贴图格式不匹配,此时就触发了API语义不匹配的问题。

该问题在绝大部分机器上并没有任何影响,仅在Kirin980、Kirin990、Exynos980这些机器上触发了超长卡顿。

切换画质卡死也类似,若在未Cache阶段渲染过太空城,此时ExShadowMap的绑定不为空,将镜头拉高到ShadowCache的层级(L2.5左右),点击切换画质会导致ExShadowFeature.Dispose,会释放掉当前的ExShadowMap,这时候又会触发Unity的默认绑定。

解决方法

保证贴图绑定正确即可。

Debug思路

开始的时候在Mate30 5G上能稳定复现。

首先想到是否是沙盘SpStarGenerator(使用了ComputeShader+IndirectDraw)引起的,考虑到在该设备上,该功能表现异常(未生效),但在L1时(SpStarGenerator的生效区间)并不会触发卡顿,且关闭该功能依然会触发,固排除(SpStarGenerator异常原因为:该设备不支持SSBO)。

多次尝试后发现问题触发在L2~L3缩放阶段,通过调整物体可见性,依次排除了星球、太阳、战略地图SVG。

发现在某些情况下不会触发,如果不触发后,该次程序启动后都不会再触发。

Profiler显示卡顿在Render线程,UI Camera的Final Blit阶段,但由于是Render线程,所以可能是干扰项(取决于GPU和Render线程的同步时间点,该提交阶段的Cmd都有嫌疑)。

FrameDebugger发现ExShadowMap为Unity的DefaultTexture

修改代码,直接关闭ExShadow功能,但Shader不做更改,则在太空城周围不缩放地图也能直接触发卡顿,确认问题所在。

其实还有个思路,可以直接用RenderDoc截一帧,由于RenderDoc可以按单次DrawCall来进行调试(类似于单步调试)。那我们直接一次DrawCall一次DrawCall的看,哪次卡顿就是哪次的锅。