当前位置: 首页 > ds >正文

srp batch

参考网址:

Unity MaterialPropertyBlock 正确用法(解决无法合批等问题)_unity_define_instanced_prop的变量无法srp合批-CSDN博客

URP | 基础CG和HLSL区别 - 哔哩哔哩 (bilibili.com)

【直播回放】Unity 批处理/GPU Instancing/SRP Batcher_哔哩哔哩_bilibili

合批分为四种:

静态合批

动态合批

gpu instance

srp batch

四个优先级排序:

按照出现的历史时间,可以大致这么排序:静态合批和动态合批较早;之后才有了gpu instance,srp batch

按照程序参与度来说:静态合批、动态合批、srp batch只需要勾选一下即可,而gpu instance则需要按照指定的约束编写shader,开启材质gpu instance功能。

从效率来说:静态合批是在build的时候,内存占用大,效率高;动态合批是在运行时的合批,消耗cpu;gpu instance是针对大量同mesh的物体的场景;而srp batch则是针对同shader的不同变体进行合批。

从优先级来说:srp batch》gpu instance

1)静态合批

静批条件:材质球相同+mesh可以不同

相同材质球、相同shader、勾选static、是在build的时候就合并为大的mesh。

mesh可以不同,在build成exe或者移动的可执行的文件的时候,就被合并成了一个大的mesh,在frame debugger中看不到合并结果,只有build之后,才能看到合并结果,通过render doc截帧才能看到。

在player settings的设置中,勾选静态合批。

2)动态合批

动批条件:材质球相同+mesh可以不同(但是必须顶点数小于300)

动态合批,在unity较早的版本,是可以在player settings中找到,并勾选,但是在新版本的unity中,urp的管线中,找不到这个勾选项了。而要在,管线配置中,勾选才行,默认是不勾选的。

默认是不勾选的原因是,dynamic batch是动态合批的,也就是在运行的时候,进行合并mesh操作。这个可能会对cpu有一定的损耗,故要权衡。

如上图所示,圆柱体和立方体,相同的材质球,相同的shader,不同的mesh可以动态合批。

但是动态合批有个特点是,当顶点数量超过300的时候,动批失败,比如将圆柱体改为胶囊体之后,动批失败。

3)gpu instance

instance条件:材质球相同+mesh相同

如下图所示,cube1和cube2是相同的mesh,相同的材质球才能被instance。

如果将cube2缓存是胶囊体,则和cube1不能被instance。

cube1和cube3无法instance,是因为他们使用的材质球不同,虽然shader相同。

shader更改为如下内容:

Shader "Unlit/xxxx"
{
Properties
{//_MainTex ("Texture", 2D) = "white" {}[PerRendererData] _BaseColor("Color", Color) = (1,1,1,1)
}
SubShader
{Tags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM#pragma multi_compile_instancing#pragma enable_d3d11_debug_symbols#pragma vertex vert#pragma fragment frag// make fog work#pragma multi_compile_fog#include "UnityCG.cginc"//float4 _BaseColor;// 如果既要srp batch又要兼顾instance就得这么写// UNITY_INSTANCING_BUFFER_START(UnityPerMaterial)//     UNITY_DEFINE_INSTANCED_PROP(float4, _BaseColor)// UNITY_INSTANCING_BUFFER_END(Props)struct appdata{float4 vertex : POSITION;//float2 uv : TEXCOORD0;UNITY_VERTEX_INPUT_INSTANCE_ID};struct v2f{//float2 uv : TEXCOORD0;UNITY_FOG_COORDS(1)float4 vertex : SV_POSITION;UNITY_VERTEX_INPUT_INSTANCE_ID};//如果只支持instance,可以这么写UNITY_INSTANCING_BUFFER_START(Props)UNITY_DEFINE_INSTANCED_PROP(float4, _BaseColor)UNITY_INSTANCING_BUFFER_END(Props)// sampler2D _MainTex;// float4 _MainTex_ST;v2f vert (appdata v){v2f o;//setup instance idUNITY_SETUP_INSTANCE_ID(v);UNITY_TRANSFER_INSTANCE_ID(v, o);//calculate the position in clip space to render the objecto.vertex = UnityObjectToClipPos(v.vertex);return o;}float4 frag (v2f i) : SV_Target{//setup instance idUNITY_SETUP_INSTANCE_ID(i);//get _Color Property from bufferfixed4 color = UNITY_ACCESS_INSTANCED_PROP(Props, _BaseColor);//Return the color the Object is rendered inreturn color;}ENDCG}
}}

UNITY_INSTANCING_BUFFER_START(UnityPerMaterial)

UNITY_DEFINE_INSTANCED_PROP(float4, _BaseColor)

UNITY_INSTANCING_BUFFER_END(Props)

这个必须是UnityPerMaterial的常量buffer,否则不能同时支持srp batch功能。

加上:multi_compile_instancing

在顶点和片段中加上instance的宏处理才行。

从图上可以看出Cube1和Cube1_1被instance了,而另外两个cube因为深度的原因被instance的两个cube打断了。这里Cube1和Cube1_1使用的是相同的材质球,但是属性不一样。同时开启材质球的instace开关:

测试2使用的是:材质属性块

using UnityEngine;public class NewBehaviourScript : MonoBehaviour
{public GameObject m_cube1;public Color m_color;private Material m_material1;private MaterialPropertyBlock propertyBlock;void Start(){if (propertyBlock == null)propertyBlock = new MaterialPropertyBlock();propertyBlock.SetColor("_BaseColor", m_color);MeshRenderer meshRenderer = m_cube1.GetComponent<MeshRenderer>();meshRenderer.SetPropertyBlock(propertyBlock);}
}

这个脚本就是将黄色和蓝色的cube在Start中改变为黄色、蓝色,使用的是MaterialPropertyBlock这个方式。为啥要使用MaterialPropertyBlock呢?假如我们改为:

Instancing and Material Property Blocks | Ronja's tutorials (ronja-tutorials.com)

using UnityEngine;public class NewBehaviourScript : MonoBehaviour
{public GameObject m_cube1;public Color m_color;private Material m_material1;private MaterialPropertyBlock propertyBlock;void Start(){if (propertyBlock == null)propertyBlock = new MaterialPropertyBlock();propertyBlock.SetColor("_BaseColor", m_color);MeshRenderer meshRenderer = m_cube1.GetComponent<MeshRenderer>();//meshRenderer.SetPropertyBlock(propertyBlock);meshRenderer.material.SetColor("_BaseColor", m_color);}
}

则会看到Cube1和Cube1_1的这两个材质球是新创建的两个材质球,但是有个优点是四个cube都能srp batch了。

同一个材质球+不同属性+shader书写要求+开启gpu instance=》才能instance。

instance的功能不受srp batch开关的影响。

Unity三种合批方式和GPU Instance - 知乎 (zhihu.com)

Unity URP中的Static Batching、GPU Instancing、SRPBatcher简单介绍_gpu instancing 和 srp batcher区别-CSDN博客

gpu instancing开启的条件:

1、首先shader必须符合gpu instancing的书写规则,如上面的例子。

2、材质需要勾选enable gpu intancing。

3、srp batcher的优先级高于gpu instaning,对于game objects,如果srp batcher能被使用(shader兼容srp batcher,节点本身也兼容),则就会使用srp batcher,即便材质开启了enable gpu instancing也没用。

4、如果srp batcher的条件被破坏,例如使用了MaterialPropertyBlock,且开启了Enable GPU Instancing,则GPU Instancing则会启用。

4)srp batch

你太逗了吧

srp batch条件:材质球不同(shader须相同)+ mesh可以不同

条件:

shader要满足srp batch的条件,将属性包在常量buffer里面。

如下图:

cube1和capusle是同材质球;cube3和cube1是不同的材质球,但是shader相同。但他们都被srp batch了。

Shader "Unlit/xxxx"
{Properties{//_MainTex ("Texture", 2D) = "white" {}_BaseColor("Color", Color) = (1,1,1,1)}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM#pragma enable_d3d11_debug_symbols#pragma vertex vert#pragma fragment frag// make fog work#pragma multi_compile_fog#include "UnityCG.cginc"//float4 _BaseColor; //_BaseColor作为单独变量声明,没有放置cb中CBUFFER_START(UnityPerMaterial)float4 _BaseColor;CBUFFER_ENDstruct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{UNITY_FOG_COORDS(1)float4 vertex : SV_POSITION;};sampler2D _MainTex;float4 _MainTex_ST;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);//o.uv = TRANSFORM_TEX(v.uv, _MainTex);UNITY_TRANSFER_FOG(o,o.vertex);return o;}float4 frag (v2f i) : SV_Target{// sample the texture//fixed4 col = tex2D(_MainTex, i.uv);// apply fogUNITY_APPLY_FOG(i.fogCoord, col);return _BaseColor;}ENDCG}}
}

1)srp batch原理

参考网址:

https://zhuanlan.zhihu.com/p/353687806

https://zhuanlan.zhihu.com/p/433222943

srp batcher使材质数据保留在gpu内存中。如果材质内容不变,srp batcher不需要设置缓冲区并将缓冲区上传到gpu。

2)兼容性

不是所有平台都支持常量缓冲区,所以unity用宏来定义区分什么时候使用。CBUFFER_START宏用来替代开始,CBUFFER_END 用来替代cbuffer的结束。

3)cbuffer

比如:unity_ObjectToWorld或者unity_SHAr。必须在一个名为UnityPerMaterial的cbuffer中声明所有材质属性。只要有一个不走常量buffer中,则合批失败。

http://www.xdnf.cn/news/113.html

相关文章:

  • langchain tools源码解析以及扩展
  • 单线服务器有什么优点
  • 【Linux学习笔记】进程调度与切换之O(1)调度算法
  • 【c语言】深入理解指针3——回调函数
  • OpenCV day6
  • 数据结构学习笔记 :树与二叉树详解
  • 学习threejs,使用EffectComposer后期处理组合器(采用RenderPass、GlitchPass渲染通道)
  • PyCharm入门导览
  • 蓝桥杯之前缀和
  • 基于单片机的温湿度采集系统(论文+源码)
  • 好数对的数目
  • 【系统分析师】-软件工程
  • 2025mathorcup妈妈杯数学建模挑战赛B 题:音智策引迁程,老城焕新颜,思路,模型,代码,持续更新中
  • 【文件操作与IO】详细解析文件操作与IO (一)
  • 15 nginx 中默认的 proxy_buffering 导致基于 http 的流式响应存在 buffer, 以 4kb 一批次返回
  • VUE3多国语言切换(国际化)
  • 数据结构初阶:二叉树(二)
  • 【MySQL数据库入门到精通】
  • 考研系列-计算机网络-第二章、物理层
  • C++_设计模式\_观察者模式(Observer Pattern)
  • .NET Core 服务实现监控可观测性最佳实践
  • 5.0.2 颜色16进制格式含义 控件template中path的使用
  • 微服务架构基础知识
  • ICPR-2025 | 让机器人在未知环境中 “听懂” 指令精准导航!VLTNet:基于视觉语言推理的零样本目标导航
  • 插入排序和希尔排序
  • R 语言科研绘图 --- 饼状图-汇总
  • 磁流变式汽车减振器创新设计与关键技术研究
  • OpenCV 中的分水岭算法的原理及其应用---图像分割的利器
  • 小红书爬虫,小红书api,小红书数据挖掘
  • 【go】什么是Go语言的GPM模型?工作流程?为什么Go语言中的GMP模型需要有P?