1
\$\begingroup\$

I have multiple calls to Graphics.DrawProcedural in my Unity-project. E.g. I'm drawing 1000 procedural geometries that share the same material and get their positions/meshes from a ComputeBuffer.

At some place in my code I'm doing something like this

foreach(ProceduralGeometry pG in proceduralGeometries)
{
    pG.Draw();
}

Where draw sets the Materials buffer accordingly and calls Graphics.DrawProcedural.

Is there anything I can do to batch all these geometries together? Currently I perform over 1000 DrawCalls (seen in the frame inspector) which happen to be very expensive performancewise.

Thanks in advance!

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Why not just collect a few buffers with different objects and direct them to compute shader?

Here is a sketched quick, not tested, example (no time to create the objects themselves). Structurally, I think it will be clear:

Compute Shader

#pragma kernel CSMain

RWTexture2D<float4> Result;

int countObj;
RWStructuredBuffer<int> obj;
RWStructuredBuffer<float3> vertexs;

[numthreads(16, 8, 1)]
void CSMain(uint3 id : SV_DispatchThreadID)
{
    for (int i = 0; i < countObj; i++)
    {
        for (int j = 0; i < obj[i]; j++)
        {
            drawVertex(vertexs[j]);
        }
    }
}

C#

class Class1 : MonoBehaviour
{
    struct Obj
    {
        public Vector3[] vertexPos;
    }

    Obj[] MyObjects = new Obj[1000];
    private Vector3[] vertexsAll;

    public ComputeShader CShader;
    private int[] VertexToObject; // Count Vertex to One object
    private ComputeBuffer obj;
    private ComputeBuffer vertexs;
    private int CountObj;

    int IdCS;


    void bufferCompiller()
    {
        CountObj = MyObjects.Length;
        VertexToObject = new int[CountObj];
        int AllCountVertex = 0;

        for (int i = 0; i < MyObjects.Length; i++)
        {
            AllCountVertex += MyObjects[i].vertexPos.Length;
        }

        vertexsAll = new Vector3[AllCountVertex];

        int IndexVertexAll = 0;
        for (int i = 0; i < MyObjects.Length; i++)
        {
            VertexToObject[i] = MyObjects[i].vertexPos.Length;
            for(int j = 0; j < MyObjects[i].vertexPos.Length; j++)
            {
                vertexsAll[IndexVertexAll] = MyObjects[i].vertexPos[j];
                IndexVertexAll++;
            }
        }

        obj = new ComputeBuffer(VertexToObject.Length, sizeof(int));
        obj.SetData(VertexToObject);

        vertexs = new ComputeBuffer(vertexsAll.Length, sizeof(float) * 3);
        vertexs.SetData(vertexsAll);

        IdCS = CShader.FindKernel("CSMain");
        CShader.SetInt("count", CountObj);

        CShader.SetBuffer(IdCS, "obj", obj);
        CShader.SetBuffer(IdCS, "vertexs", vertexs);


        CShader.Dispatch(IdCS, 32, 32 / 8, 1);
    }
}
\$\endgroup\$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .