Quick answer: In Built-in RP, multi-pass shaders render passes in source order. In URP/HDRP, only one pass normally runs per render event. For multi-pass effects in SRP, use Render Objects renderer feature or a second material on a child mesh.

Here is how to fix Unity custom shaders with multiple SubShader passes that render incorrectly. Built-in vs SRP have different rules; the “multi-pass shader” pattern requires different setup per pipeline.

The Symptom

You wrote a shader with two passes (e.g., outline + fill). In Built-in it works. In URP it shows only one pass. Or the order is reversed.

What Causes This

SRP single-pass model. URP/HDRP pick one pass per LightMode per render event. Two passes in one shader do not both run in the forward render event.

Wrong LightMode tag. Tags determine when each pass is selected; without correct tags, passes are never picked.

ZWrite/ZTest mismatch. Out-of-order depth writes cause back passes to fail depth-test against front passes.

The Fix

Step 1: For Built-in, declare passes in render order.

SubShader
{
    Tags { "Queue"="Transparent" }

    Pass // Outline back
    {
        Cull Front
        ZWrite Off
        // shader code
    }

    Pass // Fill front
    {
        Cull Back
        ZWrite On
        // shader code
    }
}

Step 2: For URP, use Render Objects feature. Add a Render Objects feature to the URP Renderer Data. Set it to render objects matching a layer or material with a custom shader pass before/after opaque, etc. The mesh renders twice with two different materials, achieving two-pass effect at pipeline level.

Step 3: Use child mesh trick for outline. Duplicate the mesh as a child slightly larger; assign outline material; set child material’s render queue lower so it draws first. Cheaper than custom render features for simple cases.

Step 4: Verify in Frame Debugger. Window → Analysis → Frame Debugger. Walk through draw calls; confirm both passes execute in the order you expect.

Step 5: Check LightMode tags per pass.

Pass
{
    Tags { "LightMode" = "UniversalForward" }
    // renders during opaque/transparent forward pass
}

Pass
{
    Tags { "LightMode" = "DepthOnly" }
    // renders during depth pre-pass
}

“Built-in supports multi-pass in source order. SRP picks one pass per event - use Render Objects or child meshes for two-pass effects.”

Related Issues

For shader keyword limit, see Keyword Limit. For Render Graph passes, see Render Graph Pass.

Built-in: passes in order. URP: Render Objects or child mesh. Same effect, different mechanism.