我是靠谱客的博主 彪壮大树,最近开发中收集的这篇文章主要介绍浅谈Batch(批次合并),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

基础知识:

1.Drawcall:
        CPU调用一次GPU的绘制函数成为一次Drawcall。

2.在执行一次Drawcall过程中,CPU的性能主要消耗在哪里?主要有两点:
        CPU在调用绘制API后,会把指令转换成和设备无关的指令(这样就能做到在所有硬件设备上兼容了),这一转换产生开销,不过开销其实并不大。
        主要的消耗在于当进行渲染状态切换时,CPU会从用户模式切换到内核模式,这一转换非常消耗性能。
        所以,减少Drawcall次数,或者更精确点来说,减少Batch次数,就可以有效舒缓CPU的压力了~

3.什么时候需要进行渲染状态切换?
        当材质不一致又或者pass不同的时候,就需要进行切换了。

4.如何减少Batch次数呢?
        尽可能把相同材质的Batch合并成一个,一次性提交给GPU处理。

1.静态合批 Static Batching:
原理:在预处理阶段,把一些材质相同的模型的顶点统一变换到世界空间坐标下,并且新构建一个大的VB把数据保存下来,在绘制时,就会把这个大的VB提交上去,只需要设置一次渲染状态,再进行多次drawcall绘画出每个子模型。 所以Static Batching是不会减少drawcall的,但由于只修改了一次渲染状态依然可以减少CPU的消耗。而且在渲染前,也可以进行视锥体剔除,减少顶点着色器对不可见的顶点的处理次数,提交GPU的效率。

限制条件:
1.static顾名思义,不能修改他的transform属性(位置,旋转等)。
2.材质必须相同。
3.不能有超级大量的相同模型(如:森林里的树)

优点:无需额外使用CPU的算力,一次渲染命令就可以同时渲染出多个独立模型。
缺点:因为需要额外维护多一份数据,所以包体会变大,占用的内存也会变多(所以才会有上面说的限制条件3)

其实总的来说,Static Batching其实就是计算机里最经典的空间换时间,以此来提升渲染效率。

2.动态合批 Dynamic Batching:
原理:在每一帧运行时,计算相同材质的模型,把他合并批次进行渲染。动态合批只需要设置一次渲染状态,且能减少drawcall次数。

限制条件:
1.材质相同
2.顶点数不能过多

优点:动态顾名思义,可以修改transform的属性,而且因为实时计算结果,所以也不需要占用运行时内存和增大包体大小

缺点:每帧都要进行合批,每帧都得运算,CPU开销较大。

静态合批VS动态合批:
        
其实静态合批和动态合批实现的大致原理是差不多的,主要是进行合批的时间点不同,一个是在编译时处理,一个是在运行时处理。 但正因为处理时间点不同,最终也产生了具体的差别:
1.静态合批在编译时处理后需要占用储存空间把数据存储下来,而且运行时加载这些数据也会占用运行内存。
2.动态合批则每帧都需要进行大量计算来进行批次合并。但以为是实时计算出结果,所以也不会出现像静态合批那样,限制Object不允许修改transform的属性。
3.静态合批和动态合批都是在CPU端进行优化处理的。
 

3.实例化渲染GPU Instancing:
        当有大量的Object,他们具有相同的Mesh和相同的Material时(例如花花草草,森林里的树木等),就可以使用GPU instancing了。因为对每个Object都会产生一个新的实例,所以可以对具体不同的实例设置不同的参数(如 color,scale)等。

4.SRP Batcher:
        前三种处理方式的出发点基本都是为了减少Batch的次数,而SPR Batcher出发点却完全不同,SPR Batcher并不会减少Batch的次数,而是减少每个Batch所需要处理的工作。其工作原理就是在GPU中设置缓冲区,用于记录存储材质相关的数据,这样就可以减少CPU发送给GPU的数据量,减少Batch的工作量了。 当场景有大量的材质而仅有少量的shader时,使用这种方式可以大幅提升效率。

在文章的最后讲一个故事:
        在一个星球上,有两块大陆,一块叫CPU,一块叫GPU,两块大陆通过一个桥梁连接着,桥梁每分钟同行一次。
        假设CPU每分钟放行一辆车过桥,那么1小时车流量才60台.(估计此时CPU上大塞车都等着过桥了吧……)
        那么假设CPU每分钟放行两台车过桥,1小时车流量就能达到120台;放行10台车,车流量就能达到600台。效率大大提升。
        这时,CPU就在想,为了我这大陆上不堵车,我不限流了,把车子大量放行过桥,可这时,GPU处理不过来了……GPU开始堵车了,CPU的车子也过不去了……

        这个故事告诉我们,当CPU忙不过来的时候,进行批次合拼,确实是可以提高效率减少性能瓶颈,可也不是说drawcall就一定是越小越好,如果当前性能瓶颈在GPU,那么即使减少了drawcall也不见得性能就有所提升。就好像假设我们在PC上玩游戏,PC的CPU运算速度足够快,减少drawcall也不会让游戏更流畅。现在的手机CPU芯片也越来越强大了,图形处理的技术也越来越成熟了(对性能的消耗降低了很多)。 对drawcall进行优化之前最好了解清楚你的游戏运行的平台,具体运行压力在CPU还是GPU,才能更合理的根据需求指定优化策略。

最后

以上就是彪壮大树为你收集整理的浅谈Batch(批次合并)的全部内容,希望文章能够帮你解决浅谈Batch(批次合并)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部