Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Discussion ComputeBuffer.CopyCount transformation ideas?

Discussion in 'Shaders' started by thebarryman, Jun 22, 2023.

  1. thebarryman

    thebarryman

    Joined:
    Nov 22, 2012
    Posts:
    122
    Are there any commonly used practices to change or transform the number that is copied from an AppendBuffer's count?

    For example, in a VR project I need to draw 2X the instances kept in an AppendBuffer. So in this case, I would want to copy Count * 2 to the draw arguments buffer used by a DrawMeshInstancedIndirect call.

    Another example is when using ComputeShader.DispatchIndirect. I want the compute shader to operate on the output of another compute shader (which is again formatted as an AppendBuffer). But in this case I want to divide the AppendBuffer's count by the target kernel's thread group size.

    Currently I am spinning up a compute shader to manually go in and change a single value in the indirect arguments buffer - seems kind of dumb? Another solution would be to GetData() and SetData(), which seems equally inelegant since you are defeating the purpose of keeping everything on the GPU.

    Any ideas?
     
  2. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,495
    Instead of using an AppendBuffer, use a Counter buffer and in your Compute you can manually call
    buffer.IncrementCounter()
    twice, effectively doubling the count as each thread will increment by 2.

    For the dividing, I don't think you have much choice but to grab the value, divide it and then assign it to the other graphics buffer from C# side, or have another kernel to run that does the math quickly and then do the CopyCount. But this would probably be worse than just grabbing the value.
     
    Last edited: Jun 23, 2023
    thebarryman likes this.
  3. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,495
    For the divide, another option might be to only call
    IncrementCounter()
    for each even thread number, resulting in half the count rounded up. Or every odd number for rounded down.
    Or for a variable division size, modulo (fmod) thread by the thread group size and increment if 0 remainder.
     
    Last edited: Jun 23, 2023
  4. thebarryman

    thebarryman

    Joined:
    Nov 22, 2012
    Posts:
    122
    Cool, thanks for those responses! I think your solution for doubling draws would totally work. This seems like a great application for Counter buffers, which I hadn't considered using previously.

    I'm not sure about the idea for the Compute indirect dispatch. Maybe for clarity, let's say "Kernel A" is directly dispatched and creates work for "Kernel B" to do via indirect dispatch.

    If I am understanding your idea, then you would be incrementing the counter from Kernel A based on Kernel A's current thread group? I don't think that would work since there would have to be a direct relationship between the number of threads for Kernel A and Kernel B. If that were the case, you could just dispatch Kernel B directly from the CPU rather than needing to dispatch it indirectly.

    The issues is that Kernel A might be processing hundreds of thousands of items, and then determine that there are thousands, hundreds, or no items at all for Kernel B to process. So I don't think it would be possible to use the thread group ID of Kernel A to determine how many threads Kernel B needs, unless I am totally misunderstanding your solution.

    In any case, thanks again for your replies.