Search Unity

What is StdRender.ApplyShader?

Discussion in 'Editor & General Support' started by TheSaviour, Nov 22, 2019.

  1. TheSaviour

    TheSaviour

    Joined:
    Apr 20, 2015
    Posts:
    68
    I've been profiling my game on an Android device and I've noticed that some spikes occasionally show up and these spikes are caused by StdRender.ApplyShader. It usually takes up around 1% of CPU usage, but during the spike it jumps to around 6%. Please check the screenshot below (btw I'm using LWRP with GPU instancing).

    ApplyShader spike.png
     
  2. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    I'm seeing the same thing, as well as SRPBRRender.ApplyShader (I'm using URP).
     
  3. RedVonix

    RedVonix

    Joined:
    Dec 13, 2011
    Posts:
    422
    Seeing the same as well in 2019.3.7f1, even with all materials sharing the same ShaderGraph based shader that is confirmed to support SRP Batcher. This is killing our performance (takes about 75ms per render pass).
     
  4. Brady

    Brady

    Joined:
    Sep 25, 2008
    Posts:
    2,474
    I had to use ShaderVariantCollections and pre-warm the shaders in an initialization script. Go to each scene and then in the Graphics settings inspector, you'll find a button to save all the tracked shader variants used in the scene so far to an asset. Here's my pre-warming script (including some timing metrics to see how long warming is taking):
    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. public class ShaderWarmer : MonoBehaviour
    6. {
    7.     public ShaderVariantCollection[] collections;
    8.     public bool Initialized { get; private set; }
    9.     private void Awake()
    10.     {
    11.         Initialized = false;
    12.         for (int i = 0; i < collections.Length; ++i)
    13.         {
    14.             if (collections[i] != null && !collections[i].isWarmedUp)
    15.             {
    16.                 System.DateTime now = System.DateTime.Now;
    17.                 collections[i].WarmUp();
    18.                 System.TimeSpan span = System.DateTime.Now - now;
    19.                 Debug.Log("Shader warming took: " + span);
    20.             }
    21.             else
    22.             {
    23.                 if (collections[i] != null)
    24.                 {
    25.                     Debug.Log("Shaders were already warm!");
    26.                 }
    27.             }
    28.         }
    29.         Initialized = true;
    30.     }
    31. }
    32.  
    If you do this at an opportune time in your game, you'll avoid unexpected runtime slowdowns. I also recommend combining these collections with this excellent UnityShaderStripper tool that will DRASTICALLY reduce your build times:

    https://github.com/SixWays/UnityShaderStripper/wiki

    Careful though, you can wind up excluding a shader you need and get unexpected behavior. But the time savings, as well as memory savings, are well worth it.
     
    filip-bencin likes this.