Search Unity

DrawProceduralIndirect, write Indirect buffer from GPU

Discussion in 'Shaders' started by MarcoGiordanoMPC2, Feb 19, 2018.

  1. MarcoGiordanoMPC2

    MarcoGiordanoMPC2

    Joined:
    Jan 19, 2018
    Posts:
    43
    Hi everyone, I am currently working on GPU culling for instances, I am able to do everything on the GPU with no intervention of the CPU, the way it works is the following:
    - Kick a compute shader to perform frustum culling, generates a buffer of ints, 0 if the instance has to be culled, 1 if has to be rendered
    - Perform a scan of the vote buffer, this will generate the scatter addresses for the instances
    - Kick a final compute shader to splat the needed geometry on a big buffer based on the scatter address
    - Do the procedural drawing.

    Now all works good and fine, except I cannot write to the indirect buffer from a compute shader, that is because, if I create the compute buffer with the indirectArgs flag, then I cannot bind to it with a view, neither with a RWStructuredBuffer or a RWByteAddressBuffer.

    Now this is a unity limitation not a DX11 one, since I have it working in stand alone application in DX11, is just a mismatch in the view creation from the unity side.
    If I try to pass both options to the compute buffer constructor, both indirectArgs and Raw, then unity tells me I cannot create it with those args (although DX11 allows it).

    Basically what I need to know for the draw indirect is the number of instances, is my understanding that the only way to achieve that is with the append buffer feature? I would rather avoid that since I assume that works with atomics under the hood?

    That means, is there a different way to be able to write the buffer and use it as indirectArgs for the draw procedurals?
    Otherwise I would be forced to get it to native side, which is not too much of an issue, just a bit more work.
     
    Last edited: Feb 19, 2018
  2. grizzly

    grizzly

    Joined:
    Dec 5, 2012
    Posts:
    357
  3. MarcoGiordanoMPC2

    MarcoGiordanoMPC2

    Joined:
    Jan 19, 2018
    Posts:
    43
    Yes, copy count works with Append buffer, which as mentioned in my post, must handle thread collision somehow, most likely atomics, So I am trying to write to that buffer directly withouth using the Append buffer feature.
    Correct me if I am wrong, but CopyCount basically downloads the hidden counter that the gpu maintains when you use append to a buffer. So this won't help me, what I am asking to do is something like this:

    This is a quick prototype of shader for a stand alone application, not unity:


    RWByteAddressBuffer inputVote: register(u0);
    RWByteAddressBuffer bufferOut : register(u1);
    RWByteAddressBuffer indirectBuffer: register(u2);
    RWByteAddressBuffer nextIteration : register(u3);
    [numthreads(32, 1, 1)] void CS(int3 tid

    .....
    //removed for brevity
    ......
    if(myId == count-1 )
    {

    indirectBuffer.Store(0 * 4, asuint(indexSize));
    indirectBuffer.Store(1 * 4, asuint(value));
    indirectBuffer.Store(2 * 4, asuint(0));
    indirectBuffer.Store(3 * 4, asuint(0));
    indirectBuffer.Store(4 * 4, asuint(0));

    }

    So IndirectBuffer, is the buffer containing the needed data to kick a indirect draw in DX11, I can write directly to it no problem using a raw buffer (i suppose a structured buffer would do), this doesn't force my algorithm to use atomic or anything. I just let one thread write to the buffer and then feed it to the DrawIndirect.
    So my question is if is possible to achieve the same in unity without going through the Append buffer feature.