DepthPass.Job and GPU Instancing

I have GPU Instancing enabled in my material and in the Frame Debugger when observing the DepthPass.Jobs I see different results for different Unity shaders:

  1. With the Unity > Mobile > Diffuse shader I see an event for each mesh, and no DrawInstanced calls.

  2. However, when I switch to the Unity Standard shader I see those events combined as DrawInstanced calls.

I’m wondering what is unique about the Standard shader? My goal is to hopefully do the same thing in my custom shader to enable DrawInstanced calls in the Depth Pass.

Look at this shader here : Unity-Built-in-Shaders/DefaultResourcesExtra/Mobile/Mobile-Diffuse.shader at master · TwoTailsGames/Unity-Built-in-Shaders · GitHub
There is no support for instancing in the shader.

Whereas here : Unity-Built-in-Shaders/DefaultResourcesExtra/Standard.shader at master · TwoTailsGames/Unity-Built-in-Shaders · GitHub
there is.

Follow this guide : Unity - Manual: Creating shaders that support GPU instancing

Sorry, I wasn’t clear. I’m creating a surface shader. My understanding was that GPU instancing works with surface shaders by default, no? I get an instanced draw call in my surface shader, I just don’t get the DepthPass.Job DrawInstanced.

It’s still not default no. You still have to add the appropriate code for it to work correctly.

hmmm. When I test this shader with GPU instancing checked DepthPass.Job goes away completely, and the Drawing is GPU Instanced without further modification:

Shader "Custom/NewSurfaceShader"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Lambert noforwardadd
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        fixed4 _Color;

        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
}

If I add a Fallback shader DepthPass.Job returns with a bunch of calls, but the drawing remains GPU Instanced.

Shader "Custom/NewSurfaceShader"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Lambert noforwardadd
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        fixed4 _Color;

        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }

    Fallback "Mobile/Diffuse"
}

Should I worry about perf with all these DepthPass.Job calls?

Based on stress test profiling, it seems the answer is yes. With 5620 low poly trees I see the following median Player Loops:

Without Fallback Shader: 6.62 ms
With Fallback Shader: 10.56 ms

Why would a Fallback Shader that’s not being used affect perf?

Think I figured it out. So based on these docs: Unity - Manual: Writing Surface Shaders , if you don’t have a shadow directive like addshadow i.e. #pragma surface surf Lambert noforwardadd addshadow then the Fallback shader’s shadow directive is used. "Mobile/Diffuse" doesn’t have a directive, so it goes to it’s Fallback shader "Mobile/VertexLit" which is a fragment shader with shadow handling that is different than whatever addshadow compiles into.

When I use #pragma surface surf Lambert noforwardadd addshadow I no longer see all the DepthPass.Job calls.

1 Like