[solved] DrawInstancedIndirect only draws at first matrix

Hi Guys!

I’m trying to use Graphics.DrawMeshInstanced() to draw multiple times a set of 3 meshes with a different shader for each. These shaders are using Ztests and stencil.
My problem is: one of the meshes of the set is only drawn once (at the matrix array’s first value) although the 2 others - that use surface shaders and stencil test - are drawn perfectly at the right place, with their right instanced properties.

The set displays as i’d like with Graphics.DrawMesh or via a meshRendererComponent. So I’m led to think I’m missing a pragma or something to make GPU Instancing work on this shader?

I also tried with it’s CommandsBuffer’s equivalent, which gives weirder results. Indeed, new problems appear: the 2 other shaders only writes then in depth without writing color. Maybe, as they are surface shaders and contain many passes, that not all passes are called?

Monobehaviour calling the Draws: (bubbles is the so-called set, it’s a prefab sent to the monobehaviour)

public class InstancerUtil_DrawInstanced : MonoBehaviour
{
    public bool debugArrayMode = false;
    [Range(1, 100)]
    public int _BubbleAmount = 10;
    public Vector2 _scaleMinMax = new Vector2(0.5f, 1f);

    public GameObject _Bubble;

    public float _offs = 1f;

    private List<Matrix4x4> _matrixArray;

    private MaterialPropertyBlock[] _propBlock;
    private Material[] _materials;
    private Mesh[] _meshes;

    // Use this for initialization
    void Start()
    {
        _matrixArray = new List<Matrix4x4>();
        // Bubbles Matrices
        var prefabScale = _Bubble.transform.localScale;
        for (int i = 0; i < _BubbleAmount; i++)
        {
            Vector3 randPos;
            float Scale= .6f;
            int j = (int)(Mathf.Sqrt(_BubbleAmount));
            randPos = new Vector3(_offs + i % j, 0, (int)(i / j)); // _offs proves that it's not drawn at origin, as changing this value has an impact on the position of the only instance drawn.
                 
            _matrixArray.Add(Matrix4x4.TRS(randPos, Quaternion.AngleAxis(-90, Vector3.right), new Vector3(Scale, Scale, Scale))); // Quaternion because meshes were exported with bad rotation.
        }
       
        // Retrieve meshes and their material from prefab
        int ChildCount = _Bubble.transform.childCount;
        _materials = new Material[ChildCount];
        _meshes = new Mesh[ChildCount];
        for (int i = 0; i < ChildCount; i++)
        {
            var child = _Bubble.transform.GetChild(i);
            _materials[i] = child.GetComponent<Renderer>().sharedMaterial;
            _materials[i].enableInstancing = true;
            _meshes[i] = child.GetComponent<MeshFilter>().sharedMesh;
        }

        // instanced Properties (works fine and there is nothing on the mesh.
        _propBlock = new MaterialPropertyBlock[ChildCount];
        Vector4[] colors = new Vector4[_BubbleAmount];
        for (int i = 0; i < _BubbleAmount; i++)
        {
            if (!ApplyVariations)
            {
                colors[i] = Color.white;
            }
            else
            {

                float r = Random.Range(0.0f, 1.0f);
                float g = Random.Range(0.0f, 1.0f);
                float b = Random.Range(0.0f, 1.0f);

                colors[i] = new Color(r, g, b);
            }
        }
        for (int i = 0; i < ChildCount; i++)
        {
            _propBlock[i] = new MaterialPropertyBlock();
            if(_materials[i].HasProperty("_Color"))
            {
                Debug.Log(_materials[i].name + "has property _Color");
                _propBlock[i].SetVectorArray("_Color", colors);
            }
        }

        // Add CommandBuffer:
       
        var cam = Camera.main;
        if (!cam)
        {
            Debug.Log("no cam selected");
            return;
        }
        CommandBuffer buf = new CommandBuffer();
        buf.name = "Bubbles";

        for (int i = 0; i < _meshes.Length; i++)
        {
            buf.DrawMeshInstanced(_meshes[i], 0, _materials[i], -1, _matrixArray.ToArray(), _BubbleAmount, _propBlock[i]);
        }
        cam.AddCommandBuffer(CameraEvent.BeforeDepthNormalsTexture, buf);
        Debug.Log(cam);

    }

    void Update()
    {
            for (int i = 0; i < _meshes.Length; i++)
            {
           
                    Graphics.DrawMeshInstanced(_meshes[i], 0,
                                                _materials[i],
                                                _matrixArray.ToArray(),
                                                _BubbleAmount,
                                                _propBlock[i],
                                                UnityEngine.Rendering.ShadowCastingMode.Off, false, 0, Camera.main);
               
            }
    }
   

}

Bad shader:

Shader "Coffee/Bubbles/StencilShader"
{
    Properties
    {
    }
        SubShader
    {
        Tags{ "RenderType" = "Opaque" }

        Cull Back
        ZTest Always
        Stencil{
            Ref 1
            Comp Always
            Pass Replace
        }

    Pass
    {
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #pragma multi_compile_instancing
        #include "UnityCG.cginc"

        struct appdata
        {
            float4 vertex : POSITION;
            float2 uv : TEXCOORD0;
        };
        struct v2f
        {
                float4 vertex : SV_POSITION;
        };
        UNITY_INSTANCING_CBUFFER_START(Props)
        UNITY_INSTANCING_CBUFFER_END
        v2f vert(appdata v)
        {
            v2f o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            return o;
        }
        fixed4 frag(v2f i) : SV_Target
        {
            return (fixed4)1;
        }


        ENDCG
    }

    Pass{ }
       
    }
}

Oops! Ok, I find it out. Answer was on GPU instancing doc page.
The mistake had nothing to do with stencil. I simply forgot to add Instance ID macros in the vertex shader and its input (UNITY_INSTANCE_ID and UNITY_SETUP_INSTANCE_ID).

Marking this as resolved.