Investigating BatchRenderer.Flush (934986)

Flush eats up 28ms when Drawinstances eats up only 1ms. Investigating in deep profile doesn’t add information in the gpu section. Zero information on what object causes that.

Google returns the same questions with no answers and Bing gets creative with suggestions about flushing your car oil.

So what is Flush? I don’t know, but I know it is related to particles.
In this example I turned off all smoke trails and left explosions. As you can see the graph in pooh-green ramps up with explosions.

All the particles in this game have bump map and use a simplified standard shader, the render path is deffered linear hdr and there are tens of lights onscreen.

It still doesn’t tell me what Flush is but it’s just the beginning…

Try with the keyword “flush unity”
first hits for me:

https://docs.unity3d.com/351/Documentation/ScriptReference/Terrain.Flush.html
http://answers.unity3d.com/questions/966616/procedurel-terrain-generation-what-exactly-does-te.html

I gues it’s not terrain so I tried unity batch renderer.flush because that’s what the autocomplete says:

Yep, all irrelevant and two that don’t know.

The twitter one seems to have a solution in the conversation

When the renderer is drawing the scene, it collects batchable objects as it walks the flattened list of “stuff to be rendered”. Every time it encounters an object that cannot be batched with the previous item, BatchRenderer.Flush is called with a list of all the items in the current batch. When batching is working well, BatchRenderer.Flush may be getting called only a few times, but with a large amount of work to do each time. Batching can be collecting dynamic batches or GPU instanced batches.

In your screenshot, the child marker “Batch.DrawInstanced” indicates that it is collecting GPU instances. Particles do not support GPU instancing, so the cause here seems unlikely to be related to particles.

The Timeline Profiler view may be able to give you better information about exactly which parts of your rendering are slow.

Here is the timeline with the particles back in.
High ms happens only when I turn the particles back on. The billboard smoke uses unity FX package with SurfaceShader_VC and custom vertex stream that’s setup in the explosion example. I’ll bet you a beer that it’s the particleI’m pretty sure it’s the particle system having trouble batching when HDR linear and defered are used in conjunction, there was a similar performance bug prior to 5.3 ( @neoshaman twit link)

3159022--240320--perf flush timeline.PNG

1 Like

Here is a perf monitor showing a high corelation: 10 missiles with that same smoke, 10 high ms flush
I changed the shader to use cutout instead of transparency and I think this cutout causes the high ms flush.

Shader "Custom/SurfaceShader_VC" {
    Properties{
        _Color("Color", Color) = (1,1,1,1)
        _MainTex("Albedo (RGB)", 2D) = "white" {}
        _Normal("Normap Map", 2D) = "bump" {}

    }
    SubShader{
    Tags{ "Queue" = "AlphaTest" "RenderType" = "TransparentCutout" }
    LOD 200

    CGPROGRAM
    #pragma surface surf Standard fullforwardshadows vertex:vert
    #pragma target 3.0

    sampler2D _MainTex;
    sampler2D _Normal;

    struct Input {
        float2 uv_MainTex;
        float4 vertex : SV_POSITION;
        float4 color : COLOR;
    };

    void vert(inout appdata_full v, out Input o)
    {
        UNITY_INITIALIZE_OUTPUT(Input, o);
        o.color = v.color;
    }

    fixed4 _Color;

    void surf(Input IN, inout SurfaceOutputStandard o) {
        // Albedo comes from a texture tinted by color
        fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
        o.Albedo = c.rgb*IN.color;
        o.Normal = UnpackNormal(tex2D(_Normal, IN.uv_MainTex));
        o.Alpha = c.a*IN.color.a;
        clip(c.a - 0.5);
    }
    ENDCG
    }
        FallBack "Diffuse"
}

Oh I didn’t spot that you are profiling the GPU, most of my previous advice was from a CPU point of view… doh!

In that case, it’s probably an expensive shader or too many particle pixels :wink:

Eg. transparency + high overdraw. Cutout can be expensive too in some situations.

Maybe experiment with reducing particle counts on specific effects (Frame Debugger may help you narrow down where exactly to focus)

I looked at the scene overdraw (should be available in the game view) and the overdraw is INSANE!
It seems that when not animated, the texture sheet animation module draws the entire sheet and clips the region that’s being rendererd, meaning that a 5x5 sprite will produce an overdraw of 25x!

I went around this bug by turning off texture sheet animation and cropping the sheets to what i need. It’s not convenient but now the Flush spike is gone.

So the solution is, when using texture sheet animation module as convenience, is to bite the bullet and crop the sheet by hand, and turn off texture sheet animation.

bug # 934986 “when texture sheet animation is fed with a float instead of an animation curve, the particle is too small by NxN and only draws 1/(NxN) thus causing a huge overdraw” that’s a mouth full.

static texture sheet animation = …
3159257--240346--sheet animation in static = massive OD.PNG
…massive OD!

and now with texture sheet animation gone, everything is smooth

1 Like

what version are you using that causes that? I can’t repo

and if true many artists using sprite sheets(atlas) to save draw calls have been greatly misguided

Oh it will save drawcall alright, but your 1080 will melt :stuck_out_tongue:
5.6.2p4

well I don’t understand, I’m just using the default particle set to identical settings and the overdraw displays no increase
5.6.2p4

We provide this constant frame mode to allow users to improve draw call batching by having different systems referencing only a single frame. This is exposed as an optimization; there should be no penalty for using it.

We only output 4 vertices, each with a UV, and the valid region of the texture is stretched over those 4 vertices. To perform clipping of the valid region would require some shader trickery, or extra vertices, which I assure you doesn’t exist, and would be a very foolish way to achieve such an effect :slight_smile:

There is no repro project on your bug, and, as Torbach has stated, the issue doesn’t seem to reproduce when trying to recreate your setup.

I’ve tried to repro with the smoke prefab from unity fx and couldn’t and since I’ve fixed it already it’s not easy.

Try getting the collab “das grind machine” project that QA has access to. The commit before yesterday’s will have that problem, “missiles enemy” will show that gigantor quad. If you’re having trouble with that, PM me a link and I’ll upload it to you.

fuck it, I’ll cut your day stress in half by not having to dig into my project, here is the narrowed down repro

You are clipping out most of your pixels with a custom shader. The problem is in your shader.

Here is a new version of SurfaceShader_VC, which exposes a “Cutout” param. Slide the slider to choose how many pixels are discarded.

Shader "Custom/SurfaceShader_VC" {
    Properties{
        _Color("Color", Color) = (1,1,1,1)
        _MainTex("Albedo (RGB)", 2D) = "white" {}
        _Normal("Normap Map", 2D) = "bump" {}
        _Cutoff ("Cutoff",range(0,1)) = 0.5

    }
    SubShader{
    Tags{ "Queue" = "AlphaTest" "RenderType" = "TransparentCutout" }
    LOD 200

    CGPROGRAM
    #pragma surface surf Standard fullforwardshadows vertex:vert
    #pragma target 3.0

    sampler2D _MainTex;
    sampler2D _Normal;

    struct Input {
        float2 uv_MainTex;
        float4 vertex : SV_POSITION;
        float4 color : COLOR;
    };

    void vert(inout appdata_full v, out Input o)
    {
        UNITY_INITIALIZE_OUTPUT(Input, o);
        o.color = v.color;
    }

    fixed4 _Color;
    uniform float _Cutoff;

    void surf(Input IN, inout SurfaceOutputStandard o) {
        // Albedo comes from a texture tinted by color
        fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
        o.Albedo = c.rgb*IN.color;
        o.Normal = UnpackNormal(tex2D(_Normal, IN.uv_MainTex));
        o.Alpha = c.a*IN.color.a;
        clip(c.a - _Cutoff);
    }
    ENDCG
    }
        FallBack "Diffuse"
}

long dragged out facepalm