See in Glossary, you can only use the SRP Batcher with the
In Unity, you can modify the properties of any Material at any time during a frame. However, this has some drawbacks. For example, there is a lot of work to do when a DrawCall is using a new Material. So the more Materials you have in a Scene, the more CPU Unity has to use to set up GPU data. The traditional way to deal with this is to reduce the number of DrawCalls to optimize the CPU rendering cost, because Unity has to set up a lot of things before issuing the DrawCall. And the real CPU cost comes from that setup, not from the GPU DrawCall itself, which is just some bytes that Unity needs to push to the GPU command buffer.
The SRP Batcher reduces the GPU setup between DrawCalls by batching a sequence of
Draw GPU commands.
To get the maximum performance for your rendering, these batches must be as large as possible. To achieve this, you can use as many different Materials with the same Shader as you want, but you must use as few Shader Variants as possible.
During the inner render loop, when Unity detects a new Material, the CPU collects all properties and sets up different constant buffers in GPU memory. The number of GPU buffers depends on how the Shader declares its CBUFFERs.
To speed up the general case where a Scene uses a lot of different Materials, but very few Shader variants, the SRP natively integrates paradigms such as GPU data persistency.
The SRP Batcher is a low-level render loop that makes Material data persist in GPU memory. If the Material content does not change, the SRP Batcher does not need to set up and upload the buffer to the GPU. Instead, the SRP Batcher uses a dedicated code path to quickly update the Unity Engine properties in a large GPU buffer, like this:
Here, the CPU only handles the Unity Engine properties, labelled Per Object large buffer in the above diagram. All Materials have persistent CBUFFERs located in GPU memory, which are ready to use. This speeds up rendering because: All Material content now persists in GPU memory. Dedicated code manages a large per-object GPU CBUFFER for all per-object properties.
For the SRP Batcher code path to render an object:
For a Shader to be compatible with the SRP Batcher:
You can see the compatibility status of a Shader in the Inspector panel.
In any given Scene, some objects compatible with the SRP Batcher, and some are not. Even when using non-compatible objects, Unity renders the Scene properly. This is because compatible objects use the SRP Batcher code path, and others use the standard SRP code path.
The overlay looks like this:
The time measurements are in milliseconds (ms), and show how much time the CPU spent in Unity SRP rendering loops.
Note: Time here equals cumulated time of all
Shadows.Draw markers that are called during a frame, regardless of the thread owner. For example, if you see 1.31ms SRP Batcher code path, maybe the draw calls have spent 0.31ms on the main thread, and 1ms is spread over all graphic jobs.
This table describes each setting in the SRP Batcher overlay that is visible in Play mode:
|Name in overlay||Description|
|(SRP batcher ON) / (SRP batcher OFF)||Indicates whether the current SRP Batcher is enabled or not. To toggle the SRP Batcher on or off, press F9.|
|CPU Rendering time||Indicates the total, cumulative amount of time that SRP loops have spent in the CPU, regardless of which multi-thread mode is being used, for example single, client/worker or graphics jobs. This is where you can see the effects of the SRP Batcher the most. To see the optimization of the batcher, try toggling it on and off to see the difference in CPU usage. In this example, the total is 2.11 milliseconds.
(incl RT idle): Indicates the idle time that the SRP has spent in the render thread. This could mean that the app was in a client/worker mode with no graphics jobs, which happens when the render thread has to wait for the graphics commands on the main thread. In this example, the render thread was idle for 0.36 milliseconds.
|SRP Batcher code path (flushes)||Indicates the time your game or app spent in the SRP Batcher code path. This is broken down into the amount of time that your game spent rendering All objects (except for shadow passes) (1.18ms), and ShadowsA UI component that adds a simple outline effect to graphic components such as Text or Image. It must be on the same GameObject as the graphic component. More info
See in Glossary (1.13ms). If the Shadows number is high, try reducing the number of shadow casting lights in your Scene, or choose a lower number of Cascades in your Render Pipeline Asset. In this example, it was 1.31ms.
The (flush(s)) number indicates how many times Unity flushed the Scene because it encountered a new Shader Variant (in this example: 89). A lower number of flushes is always better, because that means there was a low number of Shader Variants in the frame.
|Standard code path (flushes)||Indicates the time Unity spent rendering objects that are not compatible with the SRP Batcher, for example skinned meshes or particles.
In this example, the SRP Batcher flushed 81 objects in 0.80ms: 0.09ms for shadow passes and 0.71ms for all other passes.
|Global Main Loop: (FPS)||Indicates the global main loop time in milliseconds, and the equivalent in frames per secondThe frequency at which consecutive frames are displayed in a running game. More info
See in Glossary (FPS). Note. FPSSee first person shooter, frames per second.
See in Glossary is not linear, so if you see FPS increase by 20, this doesn’t necessarily mean you’ve optimized the Scene. To see whether the SRP Batcher optimizes your Scene rendering, toggle it ON and OFF, and compare the numbers under CPU Rendering time.
You can check the status on SRP Batcher “batches” in the Frame Debugger window.
To check the status of SRP Batcher batches:
The SRP Batch details show you how many draw calls were used, which keywords were attached to the Shader, and the reason why that specific draw call wasn’t batched with the previous one. In the example below, the stated reason is: Node use different shader keywords. This means that the Shader keywords for that batch are different than the keywords in the previous batch. Because the SRP Batcher used a different Shader Variant, the batch was broken. If an SRP batch has a low number of draw calls, you’re most likely using too many Shader Variants.
If you’re writing your own SRP instead of using LWRP or HDRP, try to write a generic “uber” Shader with a minimal amount of keywords (but you can use as many Material parameters and Material Properties inside each Material as you want).