Search Unity

Multiple DrawMeshInstancedIndirect???

Discussion in 'Scripting' started by FabrizioSpadaro, Jun 17, 2019.

  1. FabrizioSpadaro

    FabrizioSpadaro

    Joined:
    Jul 10, 2012
    Posts:
    287
    Hello, I have a simple question, can you call DrawMeshInstancedIndirect multiple times in a frame?
    I have a list of unique materials and I want to draw all the sprites grouped by the same material.
    Each time I call DrawMeshInstancedIndirect I pass a different material and compute buffer, but it seems to be rendering only the last time I call DrawMeshInstancedIndirect..
    Any ideas?

    Code (CSharp):
    1. class RenderInformation {
    2.   public ComputeBuffer matrixBuffer;
    3.   public ComputeBuffer argsBuffer;
    4.   public Material material;
    5.   public uint[] args;
    6. }
    Code (CSharp):
    1. for(int i = 0; i < renderInfos.Length; i++)
    2.       Graphics.DrawMeshInstancedIndirect(instanceMesh, 0, renderInfos[i].material, new Bounds(Vector2.zero, Vector3.one * 100), renderInfos[i].argsBuffer);
    3.    
     
  2. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,285
    Yes of course :)

    You haven't shared enough code for us to diagnose the problem. Maybe all your renderInfos.material are the same or something? Or all your draw calls are pointing at the same region of the same matrixBuffer, so all your drawcalls appear on top of each other?
     
    FabrizioSpadaro likes this.
  3. FabrizioSpadaro

    FabrizioSpadaro

    Joined:
    Jul 10, 2012
    Posts:
    287


    The materials are different.

    That's how I update the buffers:
    Code (CSharp):
    1. int UpdateBuffers(int renderIndex) {
    2.     ClearMatrixBuffer();
    3.     processable.SetFilter(new SpriteSheetMaterial { material = renderInfos[renderIndex].material });
    4.     NativeArray<RenderData> data = processable.ToComponentDataArray<RenderData>(Allocator.TempJob);
    5.     int instanceCount = data.Length;
    6.     Debug.Log("Material name:" + renderInfos[renderIndex].material);
    7.     Debug.Log("Entities with that material:" + instanceCount);
    8.     if(instanceCount > 0) {
    9.       NativeArray<float4x2> matrix = new NativeArray<float4x2>(instanceCount, Allocator.TempJob);
    10.       var job = new CalculateMatrixJob() {
    11.         datas = data,
    12.         matrix = matrix
    13.       };
    14.       JobHandle jobHandle = job.Schedule();
    15.       jobHandle.Complete();
    16.       renderInfos[renderIndex].matrixBuffer = new ComputeBuffer(instanceCount, 32);
    17.       renderInfos[renderIndex].matrixBuffer.SetData(job.matrix);
    18.       renderInfos[renderIndex].material.SetBuffer("matrixBuffer", renderInfos[renderIndex].matrixBuffer);
    19.       renderInfos[renderIndex].args[1] = (uint)instanceCount;
    20.       renderInfos[renderIndex].argsBuffer.SetData(renderInfos[renderIndex].args);
    21.       matrix.Dispose();
    22.     }
    23.     data.Dispose();
    24.     return instanceCount;
    25.   }
    A simple job to fast create the matrix4x2:

    Code (CSharp):
    1. [BurstCompile]
    2. struct CalculateMatrixJob : IJob {
    3.   public NativeArray<float4x2> matrix;
    4.   [ReadOnly] public NativeArray<RenderData> datas;
    5.   public void Execute() {
    6.     for(int i = 0; i < datas.Length; i++)
    7.       matrix[i] = new float4x2(datas[i].transform, datas[i].uv);
    8.   }
    9. }
    And that's how I call the whole thing:
    Code (CSharp):
    1. for(int i = 0; i < renderInfos.Length; i++) {
    2.       if(UpdateBuffers(i) > 0)
    3.         Graphics.DrawMeshInstancedIndirect(instanceMesh, 0, renderInfos[i].material, new Bounds(Vector2.zero, Vector3.one * 100), renderInfos[i].argsBuffer);
    4.     }
     
  4. FabrizioSpadaro

    FabrizioSpadaro

    Joined:
    Jul 10, 2012
    Posts:
    287
    Oh.. ok that's sad.. I was clearing all the buffers every time and that's why only the last one got rendered
    1. ClearMatrixBuffer();
    I just had to tell him to clear the buffer he is working on.
    I don't remove this post so more people can have some examples on DrawMeshInstancedIndirect
     
    richardkettlewell likes this.