使用英特尔GPA优化《轩辕传奇》游戏的性能

发表于2015-12-19
评论1 4.1k浏览
文章作者:英特尔:卢卷彬 Kiefer Kuah    腾讯:丛越

 

 

介绍

 随着集成显卡功能和性能的日益增强以及移动平台的不断普及,集成显卡已经成了游戏开发者不可忽视的重要对象。

 

 本文介绍了使用GPA在英特尔集成显卡上分析和优化《轩辕传奇》网络游戏的案例。 《轩辕传奇》是由腾讯研发团队打造的一款MMORPG网游,是腾讯的首款史诗战争网游。该游戏在引擎技术、美术、服务器等诸多方面都力求精益求精,达到了国内顶级网游水准。为了满足更多玩家的机器配置,我们特别针对集成显卡进行了测试和优化。

 

 性能分析开始

本文档的分析和优化基于Intel HD Graphics 3000平台,代号SandyBridge(简称SNB) SNBIntel2011年推出的一款性能非常出色的处理器集成显卡。它的性能可以媲美一些独立显卡。作为一款网络游戏,《轩辕传奇》的开发者希望能够在更多的平台上面流畅运行游戏,所以尽管游戏在SNB上的性能已经很流畅了,我们还是要尽量的对游戏性能进行优化。

以下是我们这次性能分析和优化所选择的目标场景: 

   

 

图1. 《轩辕传奇》性能分析和优化的目标场景

 

 系统分析

 

GPA HUD能够实时的显示游戏运行的时候CPUDX runtime,以及GPU上的性能数据。同时支持多种D3D流水线上的override模式,帮助游戏开发者进一步定位游戏的瓶颈所在。

 

通过GPA HUD的分析,我们发现:

 

1. 游戏的大多数计算都是在主线程中完成,多核心利用率比较低。那么在玩家角色多的时候,因为动画计算比较多,CPU将会成为瓶颈。可以考虑使用多线程来消除这种场景下的瓶颈。

 

2. 游戏中每帧的State Changes数量不算很多,大概每帧6000个,平均每个DP call 7.5次。能够做一些优化减少State Changes数量的话,对性能是很有好处的。

 

3. 通过Override模式测试,Null Driver, Null Hardware 都可以使游戏的fps达到100左右,100fps是游戏的限帧。所以在该场景下游戏的瓶颈是在GPU上。我们还在玩家角色比较多的场景进行了类似测试,发现Null Hardwarefps提升不大,此时瓶颈在CPU上。

 

 

帧分析

 

GPA帧分析器能够详细的分析游戏的一帧的所有draw call的性能数据以及它们所使用的纹理,d3d状态,shader等等。图2显示了我们使用GPA帧分析器打开我们在目标场景抓取的一帧数据。

 

 

 

 

 2. 使用GPA帧分析器打开抓取的一帧数据

 

 

 通过帧分析器分析,我们得到整个一帧的时间分布为:

 



    1. 生成阴影贴图:~170  DP Calls, 15.9% frame time。场景中所有的物体都计算了实时阴影。我们可以使用静态阴影来替代其中的一部分,比如某些距离远的,固定的物体。

    1. 天空盒: 3 DP Calls4.7% frame time。实际上在该场景中看不到天空,我们可以在渲染天空盒之前进行可见性检测。如果不可见,则不渲染。

    1. Terrain50 DP Calls34.9% frame time。和大多数网络游戏一样,地形总是最耗时的部分,是优化的重点。

    1. 人物和其他地上物件:~240DP Calls22.4% frame time。没有发现明显的可以优化的地方。

    1. 后处理:8DP Calls8.4% frame time。没有发现明显的可以优化的地方。

    1. UI55 DP Calls7.4% frame time。有许多UI元素过小,可以合并一下再渲染。UI并不是每帧都变化的,可以重复利用上一帧的结果。



      

优化策略和结果


 

 1. 阴影贴图生成

游戏花费了花费了~170draw calls来生成所有物体的阴影贴图,但实际上,场景中某些固定的物体或者远处的物体,是没有必要使用实时计算的阴影的,使用提前生成的静态阴影即可。这可以节省draw calls的数量,提高性能。图3是优化前后的对比,右边是优化后的阴影贴图生成,减少了使用实时阴影的物体数量,可以看到draw calls数量减少到了45个,整个阴影地图生成花费的时间从2.97ms减少到了1.03ms 

 

 

3. 优化前和优化后的阴影贴图计算

 

  2. 天空盒

 

天空盒在这个场景中是不可见的,但是帧分析器显示游戏依然渲染了它。我们可以在渲染之前检测天空盒的可见性,如果不可见,则不渲染。这可以节省0.88ms。而且,天空盒最好是放到场景中不透明物体渲染完之后再渲染,因为天空盒的大部分都是被遮挡的。 

 

 

4. 游戏渲染了不可见的天空盒

  3. 地形

  

地形部分的渲染占用了最多的时间,网络游戏一般都是这样。

 其中一部分主要的地形,占用了6.5ms中的5.1ms,它们使用的同一段Pixel Shader,以下是这部分地形的截屏: 

 

 

5. 部分地形使用同样的Shader,包含89个指令,其中13个纹理load76个算术指令

过帧分析器我们可以看到,这部分地形的渲染,PS duration占用了90%的时间,在帧分析器中我们可以在Shader Tab查看这些渲染所使用的shader code,如图5所示,这部分地形的shader 包含了89条指令,其中13个纹理load76个数学计算,比较复杂。

 

我们把shader做了一定的简化,去掉了高光,normal mapAO map等。图6是修改了pixel shader后的截图,修改后pixel shader包含31条指令,其中8个纹理load23个算术指令。 这部分地形渲染的时间从5.1ms减少到了3.4ms 

 

 

6. 优化shader代码后,这部分地形所花费的时间减少到了3.4ms

  

 我们还为特别低端的平台准备了更加简单的,只需要2个纹理的shader版本,时间进一步减少到了0.93ms,见图7所示: 

 

 

7. 在更低端平台上进一步简化地形的pixel shader

 

  当然,使用2个纹理后,地形画面质量肯定有所下降。在GPA帧分析器我们能够实时的看到修改shader code后对画面的影响。

 

 4. UI

 UI部分共占用7.4%的时间,图8是游戏中左上角的人物UI截屏。  

 

 

8. 游戏中左上角的角色UI 

 

 通过帧分析器,我们发现为了画游戏左上角的人物头像以及血槽等部分,游戏使用了9draw calls来完成(图9),而且是每一帧都会花费9draw calls来做这件事情。但是对网络游戏来说,99%的时间,这部分是不会变化的,那么每帧都使用9draw call来画这部分,是没有必要的。我们可以把这个头像部分先渲染到一个image buffer,然后使用一个draw call把这个image画到屏幕上,如果下一帧这个头像部分没有更新,则继续使用上次的这个image buffer。这样一来,只有在头像部分需要更新的时候,才去重新做这9draw calls,其他时候,只需要一个draw call就完成了。  

 

 

9. 游戏使用了9draw calls来完成这部分UI的渲染

 

 10显示了优化后的截图,这一帧重利用了image buffer,只使用了一个draw calls就完成了这部分UI的渲染。我们对其它的UI也进行了类似的优化。优化后,渲染UI所花费的时间从1.38ms减少到了1.17ms 

 

 

10. 使用image buffer来存储这部分UI以便重复使用 

 5. 减少State Changes数量

 State Changes过多会导致游戏程序,d3d runtime, 显卡驱动和显卡硬件的负载增加。减少State Changes的数量能够提高游戏性能。通过帧分析器对这一帧的详细分析,我们发现有很多的draw calls,都会使用很小的纹理,16*1632*32或者64*64大小,大量的使用小纹理,不是一种有效率的做法。图11显示了两个相邻的draw calls使用了非常小的纹理:

 

 

11. 两个相邻的draw calls,都使用了非常小的贴图

 

 从上面图11中我们看到,临近的的2draw calls,分别调用了3SETTEXTURE API,其中第二和第三个texture,都是很小的纹理(见图12)。我们可以合并这些小的纹理,然后只需要设置一次合并后的纹理,接下来的几个draw calls就可以直接使用,而不用再设置了。这可以减少State Changes的数量。当然,使用合并纹理的时候要注意设置正确的UV值。 

 

 12. 这些draw calls所使用的小尺寸纹理

 

 1314是优化后的截屏,我们合并了3draw calls所使用的小纹理,SETTEXTURE API调用的次数从9次减少到了4次。整个一帧,我们减少了~500State Changes 

  

13. 合并纹理后,3draw calls所调用的SETTEXTURE API9次减少到了4 

 

 

14. 将小纹理合并后得到的大纹理

    

优化总结:

 

我们介绍了在英特尔集成显卡平台上通过GPA对游戏性能进行分析和优化的成功案例。GPA工具帮助我们找到了游戏的瓶颈所在。我们使用它对一帧进行了深入的分析,对shader进行了实时修改,并找到了减少State changes数量的办法。经过优化,游戏性能得到了很大提升,能让更多玩家流畅体验轩辕传奇这款游戏。其实我们还使用GPA对其他不同场景,不同状态(聊天,骑乘,战斗,换装,技能特效等),不同平台(各个厂商的独立显卡,集成显卡以及不同型号的CPU),不同系统进行了各种测试,限于篇幅这里只挑出了一个有代表性的例子。


   

作者简介

卢卷彬 是英特尔公司的应用工程师,他和国内几家大的游戏公司有着多年的合作,帮助他们在英特尔平台上优化游戏客户端的性能。

丛越 8年以上的游戏开发经验,他参加了中国最早期的3D MMORPG的开发,有着非常丰富的经验。丛越现在就职于腾讯,主要负责游戏和引擎的开发。

Kiefer Kuah 是英特尔的软件工程师,他主要负责游戏在英特尔平台上的优化工作。

 


 Appendix A:

Platform Configuration:CPU:  Intel Core i7-2720QM @ 2.20GHz, with HD 3000 graphics

Memory: 8GB DDR3 1333Mhz

HD: Intel 160G SSD

OS: Windows 7 Professional, 64bit

Graphics Driver: 8.15.10.2509

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引