可以简单的理解为:批量渲染是通过减少CPU向GPU发送渲染命令(DrawCall)的次数,以及减少GPU切换渲染状态的次数,尽量让GPU一次多做一些事情,来提升逻辑线和渲染线的整体效率。但这是建立在GPU相对空闲,而CPU把更多的时间都耗费在渲染命令的提交上时,才有意义。
合批最重要的前提:材质必须相同!!!
合批是节省了CPU的相关准备工作的工作量。
合批后,经过VS,PS,尝试测试,模板测试后,此时已没有了纹理,顶点,索引的概念,只剩下一个个孤立的像素,各像素间没有任何关系了。像素送到GPU后进行批量处理,呈现到屏幕硬件上。因此合批与GPU没有任何关系,也几乎没有影响。不管是一批还是多批,最终在此帧送到GPU的像素数量是相等的,数据是相同的。分成多批,是一帧内将像素数据分多次提交给GPU。合批与否,对GPU的影响仅是像素到达的慢了还是快了,几乎不影响GPU的性能。
一、离线合批(Offline Batch)
离线合批就是在游戏运行前,先用工具把相关资源做合批处理,以减轻引擎实时合批的负担。
适合离线合批的是静态模型和场景物件。如场景地表装饰面:石头/砖块等等。
离线合批方式有:
- 美术利用专业建模工具合批。如3D Max/Maya等。
- 利用引擎插件或工具。如Unity的插件MeshBaker和DrawCallMinimizer,可以将静态物体进行合批。
这里有500+的cube其实都是在同一个cube复制出来只需要记录一个Transform就可以啦,给他一个变换矩阵、可以是缩放、平移、旋转等等;包括gltf里面也可以直接实现实例化!
水就是用了实例化技术translation里做了平移。更好的学习例子openglleran 实例化小行星带

Draw Call 本质与现代的DC问题
当Mesh数据大小一样的前提下 draw call 渲染指令传的次数越少越快! (就好像 30W 顶点 cpu 总共向GPU传递3次 每次10W 快 cpu 总共向GPU传递1000次 每次300个快GPU一直在等待CPU!本质上就是说现代的gpu速度已经远远甩开啦cpu的速度 不是一个数量级的。一次性处理30个顶点和一次性处理10000顶点没有什么区别 GPU早就处理完了一直在等待Cpu传(或者这样表述:
“现代GPU的计算性能其实性能很高,并行渲染计算速度很快,如果CPU向GPU传递的数据不够的话,GPU的计算能力不能被充分利,所以瓶颈在CPU
不是在GPU ,CPU与GPU数量级相差是的三次方到六次方 甩开的很远”
)
更详细是这样的: cpu到gpu的通信是 先吧数据加载到 显存 设置渲染状态 然后cpu调用渲染命令才开始(dc)才到渲染管线。就是gpu已经处理完了 指令池中的指令 还没等到cpu的指令 cpu还在设置渲染状态等等(也是俗称的 上下文比如opengl的上下文或者dx )相同材质 光照 渲染状态是一致的 所以合批要相同材质的 mesh才可以 渲染状态很多比如深度测试与写入 、透明的混合 等等。就像上面举的例子传递3次每次10W顶点,CPU渲染状态只需要设置三次。但是如果是传1000次每次300顶点CPU设置渲染状态需要1000次,GPU利用率很低而CPU太浪费了,因为这1000次中有大部分相同!
对于刚刚上面说的需要更正一点的是:数据和指令并不是串行执行的。指令推送到PushBuffer与数据DMA传送是可以同时进行。在OpenGL这里,你的渲染数据也不一定存储在显存。具体什么时候做数据调度和流水线的驱动实现有关。而且现代的图形API都已经可以做到指令并行执行,DC已经不是一个瓶颈了,更何况有IndirectDraw这些trick,可以做GPU driven rendering。只不过需要自己去注意资源和状态之间的互斥关系,自己来处理锁。
对于性能分析:GPU等CPU出现的情况就是CPU太忙GPU太闲,一般CPU测回执行绘制指令的组织,包括各种算法提升渲染速度尽可能的减少绘制指令这些都是有开销的,或者在极端一点,外面一个多线程应用占用了99%的CPU资源,你能提供分摊到组织渲染的算力少的可怜所以你要分析你们的软件有没有别的功能占用了CPU。
参考资料:
想对硬件cpu gpu了解的分享一个好文章 前同事写的虎牙大佬
深入GPU硬件架构及运行机制
游戏图形批量渲染及优化:Unity静态合批技术
动态合批和静态合批的区别
实例化
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!