赞
踩
批处理:在3D图形中,批处理是一个非常通用的术语,描述了将大量任意数据块组合在一起并将它们作为单个大数据块进行处理的过程。本文中的批处理通常指用于批处理网格数据的机制。
动态批处理和静态批处理这两种方法本质上是几何体合并的两种不同形式,用于将多个对象的网格数据合并到一起,并在单一指令中渲染它们,而不是单独准备和绘制每个几何体。
很多地方模糊的说 批处理原理是是减少Draw Call,其实严格来说并不对。
其中静态批处理并没有减少DC数量。那静态批处理是优化的什么呢?
首先DC是什么就不赘述了,DC之所以造成性能瓶颈是因为CPU每次为提交GPU所准备的数据和设置渲染状态而消耗了太多的时间。所以如果渲染状态不变,在多次DC调用之间并没有渲染状态的切换,渲染API(Command Buffer)会缓存绘制命令,起到了渲染优化的目的 。
批处理提升此过程的性能诀窍在于,新的DC并不一定意味着必须配置新的渲染状态。如果两个对象共享完全相同的渲染状态信息,那么GPU可以立刻开始渲染新对象,因为在最后一个对象完成渲染后,还维护这相同的渲染状态,这消除了由于同步渲染状态而浪费的时间,也减少了需要推入命令缓冲区CommandBuffer中的指令数,减少了CPU和GPU的工作负载。
动态批处理的工作原理:将所有游戏对象顶点转换到 CPU 上的世界空间,所以仅在该工作小于进行绘制调用的情况下,才有优势。绘制调用的资源需求取决于许多因素,主要是使用的图形 API。例如,对于游戏主机或诸如 Apple Metal 之类的现代 API,绘制调用的开销通常低得多,通常动态批处理根本没有优势。------引自2018.4官方文档
静态批处理的工作原理:将静态游戏对象转换到世界空间并为它们构建一个共享的顶点和索引缓冲区。如果已启用 Optimized Mesh Data__(in the Player settings),则 Unity 会在构建顶点缓冲区时删除任何着色器变体未使用的任何顶点元素。为了执行此操作,系统会进行一些特殊的关键字检查;例如,如果 Unity 未检测到 LIGHTMAP_ON 关键字,则会从批处理中删除光照贴图 UV。然后,针对同一批次中的可见游戏对象,Unity 会执行一系列简单的绘制调用,每次调用之间几乎没有状态变化。在技术上,Unity 不会减少 API 绘制调用,而是减少它们之间的状态变化(这正是消耗大量资源的部分)。在大多数平台上,批处理限制为 64k 个顶点和 64k 个索引(OpenGLES 上为 48k 个索引,在 macOS 上为 32k 个索引)。------引自2018.4官方文档
手动组合彼此接近的游戏对象,比批处理效果更好。例如,一个带有大量抽屉的静态橱柜通常只需在 3D 建模应用程序中或者使用 Mesh.CombineMeshes 来组合成一个网格。----引自2018.4官方文档
https://docs.unity3d.com/2018.4/Documentation/Manual/DrawCallBatching.html
注意:批次不是越少越好,过大的渲染数据会给内存带宽带来压力,拉高峰值波动上限。
Edit->Project Settings->Player->Other Settings-> disable Static Batching and Dynamic Batching
如果没有开启,可以看看上面设置是否禁用了批处理。
如果禁用了动态批处理,那么多个共用材质的物体并没有减少dc数量,这是因为渲染状态变更的数量并没有真正减少,也没有合并网格信息。渲染管线不知道我们在重复的写入相同的渲染状态,一次一次渲染相同的网格。
这个工具直观的区分两个连续的Draw Call。很容易准确地指出给定的Draw Call渲染了哪些对象。这可以通过查看在Draw Call期间出现了多少个对象,来帮助确定是否对一组对象进行批处理。
单击Frame Debugger中的一个Draw Call项,就会显示标签为“Why this draw call can’t be batched with the previous one(这个Draw Call为什么不能与前一个Draw Call批处理)”的部分。大多数情况下,下方的解释文本说明了哪个条件没有满足(至少是它检测到的首个条件),以及有什么调试批处理行为的有用方法。
动态批处理通过将所有物体的顶点转换为CPU上的世界空间来工作,所以它只能在渲染Draw Call的工作量小于CPU顶点转换工作量的时候,才会起到提高性能的作用。
解释:
一. 顶点属性包含:定点位置,法线向量,UV坐标,定点颜色等。属性数据越多,900个预算消耗的越多,从而减少了网格允许拥有的定点数量。因此只有相对简单的对象才适合动态批处理。如下图,查看verts值:(只有在引擎内看到的数据为最终数量,在从建模工具中导入时会改变)
例1:cube 仅仅包含8个顶点,每个顶点有 位置、法线、UV数据,总共24个。远低于300个顶点和900个顶点上限。 可以批处理。
例2:球体包含515个顶点,总共1545个顶点属性,所以不能动态批处理。
二. 网格缩放:
等比缩放:(1,1,1) 和(2,2,2)可以合并,因为是等比缩放,虽然比例不同。
非等不缩放:(2,1,1)(2,2,1)可以合并为另一个,因为是非等比缩放。
注意:负数缩放会导致奇怪情况,这与三个值中哪个是负数无关,与负数值是否为奇数或者偶数有关。同时负数时,渲染顺序还会导致合批失败
两个对象使用不同的纹理,最好合并纹理(通常称为图集),并重新生成网格UV,以便进行动态批处理。这虽然会牺牲纹理的质量或者文件变大,或者纹理文件会变大GPU内存带宽压力大,但这是值得的。
unity静态批处理不是真正意义上的"静态批处理"把勾上的合并成一个mesh,而是首先unity会先按照渲染顺序动态排序以及静态批处理的可视处理。因为球没有勾选static,然后插在了4个cube中间的渲染顺序(或者说挡住了某一个cube时,处于不可视的时候),这样unity就会先渲染2次合并后的Combined Mesh,第一次渲染球前面的Combined Mesh,第二次渲染球后面的combined mesh,因为这个球插足了破坏了合批,所以就是3个batches。而更换角度后,球没有插足cube的渲染顺序,所以就不会破坏合批。(背景,不透明。渲染顺序基本稳定的,先渲染的。)
静态批处理将所有标记为Static的可见网格数据复制到一个更大的网格数据缓冲中,并通过一个Draw Call传到管线渲染中,同时忽略原始网格。如果所有进行静态批处理的网格都各不相同,那么与正常渲染对象相比,这不会增加内存使用量。
但是,通常渲染一万个相同对象,消耗的内存是相同的,因为引用相同的网格数据。在这种情况下,对象之间的唯一区别是每个对象的变换。然而静态批处理的引用会丢失,所以使用静态批处理渲染1000个相同的树对象,消耗的内存是不使用的1000倍。会导致严重的内存消耗。
如果需要动态实例化,或者使用叠加方式加载场景,可以使用StaticBatchUntility.Combine() 两个重载形式:
缺点:强大但危险的工具。很容易造成内存消耗(导致应用程序崩溃)。还需要大量手动调整和配置,以确保正确生成批处理。
优点:可以使用不同形状和巨大尺寸的网格,这是动态批处理无法提供的。
在使用相同材质球、相同Mesh(预设体的实例会自动地使用相同的网格模型和材质)的情况下,Unity会在运行时对于正在视野中的符合要求的所有对象使用Constant Buffer[5]将其位置、缩放、uv偏移、lightmapindex等相关信息保存在显存中的“统一/常量缓冲器”[6]中,然后从中抽取一个对象作为实例送入渲染流程,当在执行DrawCall操作后,从显存中取出实例的部分共享信息与从GPU常量缓冲器中取出对应对象的相关信息一并传递到下一渲染阶段,与此同时,不同的着色器阶段可以从缓存区中直接获取到需要的常量,不用设置两次常量。
不严谨的人话:GPU多例化技术原理简单,就是先把数据提交到显存中,然后在绘制时,修改一些属性,就能达到避免N次设置渲染状态造成的性能消耗。不同的物体靠参数属性的不同进行区分。
在某些场合是我已知唯一的处理优化手段。比如几千棵树,几万株草的草地。
GPU Instancing在减少DC的同时,也避免了内存的爆炸。
2018版本已经支持GI,不用再手写了。
操作过多。如果使用自定义Shader,则需要修改代码
由于constant buffer的限制(默认是500),DC数量也会缓慢增加
在使用LWRP或者HWRP时,开启SRP Batcher的情况下,只要物体的Shader中变体一致,就可以启用SRP Batcher加速。它与上文GPU Instancing实现的原理相近,Unity会在运行时对于正在视野中的符合要求的所有对象使用“Per Object” GPU BUFFER(一个独立的Buffer) 将其位置、缩放、uv偏移、lightmapindex等相关信息保存在GPU内存中,同时也会将正在视野中的符合要求的所有对象使用Constant Buffer[5]将材质信息保存在保存在显存中的“统一/常量缓冲器”[6]中。
(LWRP是老版本的叫法,新的忘记了)
批处理可以合并不同的mesh,而GPU Instancing主要是针对同一个mesh。
当物体顶点数量级别较大,重复度较低时,选择静态批处理(场景模型);
当物体顶点数较少且数量较少时,可以按需求选择动态批处理,当超过一定级别数时(参考:20个顶点的物体,数量超过3000)选择GPU Instancing将更有优势,且数量越多,优势越明显。
必读: http://newhappy.com.cn/index.php/2020/05/14/batch/
必读:关于静态批处理/动态批处理/GPU Instancing /SRP Batcher的详细剖析
必读:利用GPU实现大规模动画角色渲染
1.《Unity游戏优化》第二版
2. 官方网站文档-批处理
3. 官方文档-GPU多例化
4. GPU多例化
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。