A Unity ID allows you to buy and/or subscribe to Unity products and services, shop in the Asset Store and participate
in the Unity community.
Discussion in 'Graphics Experimental Previews' started by PhilSA, Apr 18, 2018.
The release notes of 2018.2b1 mention this:
More info on what this is?
I have not been able to find documentation for this feature - how it works, what breaks batching, what are the limitations etc. I've googled around but have only found announcement posts (SRP Batcher is released!) but nothing technical. Anyone have any links?
There isn't really anything at this point. I've found that as of 18.3 Shaders, if viewed in the Inspector will show "SRP Batcher Compatible" or a reason why it is incompatible, most commonly that the Constant Buffers must be uniform across all Passes/Variants. In my tests I've seen some differences in between SRP Batcher On/Off but cannot discern what exactly has changed.
Hope we get some more info soon. It seems really powerful. I have a scene with a bunch of different materials with different properties. It seems that as long as they are the same shader, and use the same keywords, they can be batched together. Very very cool.
It would be cool if this could somehow be done on a per shader pass basis as well. For example, whether my workflow is metallic or specular, the shadow caster pass will look the same! The shadow pass doesnt care about these keywords. Yet the SRP batching breaks when rendering shadows if my materials have 2 different workflow modes active. Maybe if the shader pass exposed some metadata regarding which keywords 'it contains', so when Unity is rendering the shadows the SRP Batcher will see that the 2 materials have different keywords, buuuut the keywords that are different aren't used in the shadow pass, so they could be batched together anyway!
Recently came across this now again. There is:
But yeah... not very helpful.
Anyone knows yet what this is doing under the hood?
Hi! We should communicate about SRP batcher. Blog post is coming soon. I can give you some information here.
Basically "SRP batcher" is a generic name for "SRP dedicated c++ rendering inner loop". In standard Unity, setting a new material is quite CPU consuming. Worst case scenario would be a scene with 1000 meshes, each one use its own material (for instance with diffuse texture and albedo color change)
With SRP batcher, changing material is way faster than before ( because material data are now persistent in GPU ). You just have to use same shader, but you can have any number of materials. In the previous case ( 1000 meshes with 1000 different material), the CPU speedup factor is about 5 times! ( measured on "RenderLoop.Draw" and "ShadowLoop.Draw" CPU profiling labels)
If you want to play with and do some test on your own project, you could use that nice profiler script. Press F8 to toggle profiling information on screen, and press F9 to toggle ON/OFF SRP batcher.
Feel free to ask questions about SRP batcher here.
That's great! Thanks Arnaud. Sounds like the exact thing I need for our use case.
Is there any special care we need to take in the shader? Just make sure everything is in a constant buffer or?
are you writing your own SRP or use existing LWRP or HDRP? there are some rules to respect in your shader to be SRP batcher compatible. If you don't respect the rule, the object is still properly rendered, using the standard unity rendering code path. When you look in the shader inspector in a SRP based project, you can see a line "SRP batcher: Compatible or Nor compatible" with a reason why it's not compatible.
But basically, unity "built-in" vars should be located in a CBUFFER named "UnityPerDraw" ( you can have a look in LWRP or HDRP). You should use the same for your own SRP
Most important, all your "material" vars should be located in a CBUFFER called "UnityPerMaterial". ( so all vars declared in the shader property section should be in "UnityPerMaterial" CBUFFER
Again, shader inspector with "SRP batcher compatibility" hint is really usefull to see what is wrong in the shader to be SRP batcher compatible
Makes sense! That's very doable. It's a custom SRP (it's for Manifold Garden, quite stylized rendering).
We're shamefully on 2017.4 still, but this might be a good pish to migrate, will do some perf tests for some of our levels soon.
I just looked at a "Manifold Garden" trailer video, looks nice. Btw seems to be really monochromatic. I guess you don't have so many different materials in that kind of scene right? Less you have material, less will be the SRP batcher speedup.
Manifold Garden is quite awesome! are you guys using a custom SRP or one of the ones we provide?
Ah thanks! It's been so long in dev that SRP wasn't really an option. However, at some point we made our own shadow mapping system since the legacy pipe requires rendering the scene twice for cascades. That kept giving us headaches so.. finally converted our hacked together pipe into an SRP now Definitely cleaned our code up tons, will compare perf properly somtime
The SRP batcher should be perfect indeed. The world wrapping means we can end up with quite a few draw calls despite combining as many objects as we can & instance rendering.
Hi @arnaud-carre and @phil_lira, I am just wondering if SRP Batcher actual works in 2018.x releases?
Only SRP 5.x release has SRP Batcher options available, so does it mean SRP Batcher is only for 2019.x releases?
(Also I can't seem to find the "SRP Batcher Compatible" wording in inspector, I must be missing something...)
SRP batcher has been released in 2018.3, but "SRP Batcher Compatible" wording is 2019.1. ( be carefull the wording is active only if you're using a SRP project)
About enabling the batcher, even if SRP didn't expose the "SRP batcher" flag, you can activate it using script ( use miniprofiler.cs script provided in this thread)
Hi I just tested your mini profiler script, very helpful!
It seems useScriptableRenderPipelineBatching is not set to true by default? Is it still in preview on 2018.3?
Hi, useScriptableRenderPipelineBatching is true by default in 2019.1 but should work correctly in 2018.3 too
Current SRP Batcher has issues with large meshes that contain more than one submesh/material (apparently only reproduced with DX11 so far). Just mentioning it here in case others stumble on the same thing. Issue report here if people want to follow it:
For non-technical people out there, Unity defaults to 32-bit vertex index buffer for meshes with >65k vertices, otherwise it uses 16-bit indices for it and that still works with submeshes using the SRP batcher. You can also manually force a bigger mesh to use 16-bit indexing and Unity will then split your mesh into smaller chunks so they can fit into that buffer.
thanks for reporting. The issue has been fixed in our current code base ( so 2019.2 ). Issue only affect dx11, SRP batcher with 32bits indexed mesh used in additional sub-meshes. ( so currently if you have a 32bits mesh without any additional submesh, everything should be ok).
Oh cool, so next question really is, will the fix be backported to 2019.1?
In my test, Renderer.SetPropertyBlock breaks the SRP batching.
Are there any rules or restrictions to use MaterialPropertyBlock with SRP Batcher?
The test is on my own SRP on Unity2018.3.1f1
SRP batcher does not handle MaterialPropertyBlocks. Now Material GPU data is persistent, so better use different material instead of MPB when using SRP batcher.
In the standard system, if I recall correctly, applying a MPB to a renderer breaks batching momentarily, but the object is once again batched when the MPB is removed. What kind of behaviour can we expect from the SRP batcher? We use MPBs quite extensively for making temporary property changes to materials, e.g. ramping up emission strength for a certain duration.
I understand that no MPB and all unique material data on GPU persistently.
Are there any way to use SRP batcher with a shader that includes UNITY_INSTANCING_BUFFER?
The “unity_InstanceID” looks like working with SRP batcher, so if there is a way to set user property per GPU instance, it helps.
I did it with MPB that sets to shader’s UNITY_INSTANCING_BUFFER property, before SRP batcher..
Maybe the GPU instances that dynamically spread on runtime can use material instance for each.
But the spread assets on editor with various value in property (and render as GPU instance, with SRP batcher) will need some way to set unique value on editor.
ekakiya: Currently SRP batcher didn't do any GPU instancing. If you really need GPU instancing then you can explicitly use DrawMeshInstanced, which is fastest way of doing instancing in unity ( of course it's up to you to setup the right data per instances in c#)
for temporary transition like you describe, you can still use MPB as you describe. It will obviously break the batch, but if you do it on a small amount of object and transition is temporary, it may be ok.
If you have many objects that are in transition at same time, then maybe you should create a new material instance for each one, even for temporary transition. So you still has the cost of dynamic material values and GPU data upload ( as you also have with MPB) but you keep all objects in one SRP batch.
Hi Arnaud, I wonder more about the best way to work with SRP batcher? What is the best way to optimise the project so SRP batcher can work more efficiently, for higher framerates?
We batch by shader now?
I think this is the key takeaway here:
So basically to get the most out of this, you'd want to use same shader for as many objects as possible. You can use different materials for them, just base them on same base shader/shader graph. I'd assume that the ideal workflow would be to consolidate some of the things from multiple shaders into fewer to get most out of this, just don't put everything to one expensive shader or your perf benefits get hurt from that instead.
@arnaud-carre can you clarify what you mean by "same shader" in this context? Does that only mean "same" as in "same specific variant" of the shader or can you still use different shader switches for the batcher to put things on the same batch? For example if you put HD Lit on your materials but others use Opaque and others use Translucent setting, would it be put to separate batches? (I'd assume it would be treated as separate batch but better ask to be sure).
yes, when I mean same shader it's really same shader variant. ( I mean, same shader microcode ). If a new keyword is used for a shader ( for instance LOD-fade ) then the batch will break because we have to change the shader program itself.
But to be optimal, just keep the idea of having minimal number of shaders. also now you can use as many material as you wish.
We're preparing a blog post about how SRP batcher is working and how to use it at his best. I noticed more and more people are interested.
Rizu: about Opaque and Translucent. for this case, there will be two different rendering passes so yes they will be in separate batches ( but that's perfectly normal for different passes)
Hi, just a follow up question: when GraphicsSettings.useScriptableRenderPipelineBatching is true, does Frame Debugger / Game view's "Stats" HUD currently display incorrect info?
In particular, I found that my custom shader global property is not showing up in Frame Debugger when SRP batcher is enabled. And the opaque pass seem to only show 1 draw, which doesn't add up to either Batches/SetPass number.
I am using Unity 2018.3 latest.
Unity 2019.2.0a6 states: SRP batcher is now supported on OpenGL 4.2+ and OpenGL ES 3.1+
Is There any plans to support OpenGL ES 3.0+ in future?
If no, what is best practices to support both devices with gles 3.1 and gles 3.0?
Looks like another user is reporting the same problem at the blog post comment section:
Just a quick check: unity team already knew this right? I don't need to submit a bug report for you to track? @arnaud-carre
@arnaud-carre for some reason the SRP Batch code path isn't running for me when VR is enabled in my project. This was replicated in a clean project with just art and unmodifed code as well:
Unmodified version of LWRP
VR Enabled (Single Pass Instanced)
SRP Batching Enabled in Lightweight Render Pipeline Asset.
Graphics Jobs Enabled
All materials in scene are using the Lit shader provided by LWRP.
SRP Batching Profiler (and frame debugger) reveal that the SRP Batches aren't happening.
If VR is disabled (or if frame debugger is sampled while play mode is inactive in editor)
SRP Batching works as expected.
Is there something I'm overlooking?
I have changed my project's rendering pipeline to LWRP a few weeks ago and I can't seem to toggle this feature on.
Inspecting any shader (even LWRP's default lit shader) does not show the "SRP Batcher Compatible" field.
Should static batching be disabled when using SRP Batcher? Do you have any recommendation for that?
Sorry the blogpost didn't mentioned that. VR with SinglePassInstanced mode is supported in 2019.2 (at least after 2019.2.0a4 )
What Unity version are you using? If you already see "SRP Batcher Compatible" field one time, and not anymore, then it means you don't use a SRP based project. Maybe your SRP assert in graphics settings is not set properly?
Static batching is still supported with SRP batcher and recommended.
Static batching is always a better choice with SRP? What about lots of small objects statically batched? I mean, I guess the advice for what should be statically batched is a different discussion for performance.
Bigger levels (for example 1x1 km or larger): Static batching isn't feasible anymore. It costs a lot of memory (we had several GB's combined mesh data). It increases loading times significantly. At one point, mesh memory became so much, that it actually slowed down rendering significantly. Using GPU Instancing was the better option in this case. I was testing on console.
Smallish levels: Static batching is a great option.
I've never seen the SRP Batcher Compatible field in this project, despite the fact that I'm running the latest LWRP from the package manager.
I made a new project and added the LWRP package to it and I can see the SRP Batcher Compatible field in it just fine.
Agreed, I felt @arnaud-carre advice here was a bit suspect. I think static batching itself isn't a good concept at all, perhaps a better concept is HLOD, which seems supported on the hybrid renderer.
Any reason why the option doesn't show up on my Unity? Please advise
I got bored of waiting for a confirmation, so here is my bug report case number: 1134372 (Frame Debugger is showing incorrect stats when SRP Batcher is enabled via scripting)
This is the issue I am seeing (with SRP Batcher enabled, Depth and Opaque pass provides no data and is always 1 draw call in my test, on Unity 2018.3.6f1):
PS: honestly I am not even sure the Stats HUD is correct. I guess only the mini profiler script data is reliable.
Now this is something amazing: I just updated to 2018.3.7f1 (from 2018.3.6f1), and somehow this issue is gone.
Didn't see anything related to Frame Debugger or SRP in the release note, but sure, I gladly take it.
Well, if static batching is working in your level ( same material, objects close to each other, etc) then it's efficient from a CPU point of view. Inner engine loop will just do "draw, draw, draw" for each mesh ( instead of "bind, draw, bind, draw, bind, draw). Plus, CPU will build less UnityPerDraw CBUFFER at runtime. But in practice, it's quite hard to do a scene with objects that could be static batched. ( too much constraints)
But this is only CPU consideration. If memory is an issue in your project, then yes static batching could increase memory usage.
As always, my advice is: profile in your dedicated scene.
Thank you for clarification, I will take another look at static batching. Not sure why it was slower for me in previous attempts to use it.
Is the SRP Batcher supposed to work in Edit Mode? The last video in blog post shows it working in edit mode on megacity, but in my project it doesn't work until I hit play.
This makes a scene that runs well in Play Mode nearly unusable in Edit Mode and makes it so we effectively have to still optimize our assets for the old material + GPU instancing model in order to have reasonable editing performance.
Tested on 2018.3.10f1 with hdrp 4.10.0-preview.