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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question How to pass ComputeBuffer consisting of "ushort" datatypes to compute shader? and how to use it?

Discussion in 'Shaders' started by unity_3KoGAU6lZHRhFA, Apr 29, 2023.

  1. unity_3KoGAU6lZHRhFA

    unity_3KoGAU6lZHRhFA

    Joined:
    Jul 26, 2022
    Posts:
    7
    When there's a lot of data to process, half the question is about how to compute it, and the other half is about how to store it in memory.
    i am talking about literally tens of millions of variables to process every second, the data is stored as a 3d array. and the only meaningful way to compute all of this, is with the parallelism of GPU.

    Compute shader and so on. Problem solved, right? Wrong. there's the "memory" part of the question.
    The data is highly optimized, it uses "ushort" type in C#. imagine the data in pseudo-code like:

    Code (CSharp):
    1. Array [
    2.     (ushort, ushort, ushort) element1,
    3.     (ushort, ushort, ushort) element2,
    4.     (ushort, ushort, ushort) element3,
    5.     (ushort, ushort, ushort) element4,
    6.     (ushort, ushort, ushort) element5,
    7.     (ushort, ushort, ushort) element6,
    8.     ...
    9. ];
    Question:
    How am i supposed to give that data to the Compute shader when there's no 16 bit unsigned integer datatype provided? I know i can use some bit-wise tricks but i can barely see the whole picture, i need a more elaborate answer. specifically, how do i need to specify the buffer in C# and how to define that buffer in shader in an efficient way? and if it's gonna be aligned differently, how to sample it knowing the index x y z?
     
  2. Thomas-Mountainborn

    Thomas-Mountainborn

    Joined:
    Jun 11, 2015
    Posts:
    489
    I just ran into this yesterday with mesh index buffers, which can also be ushorts. They also happen to be packed in threes. Here's what the compute shader can look like:

    StructuredBuffer<uint> IndexBuffer;

    uint2 UnpackUShort2(uint packedValue)
    {
    // The indices are ushorts, which aren't available as a type in compute. Separate them here.
    return uint2(packedValue & 0xFFFF, packedValue >> 16);
    }

    Use this method in the kernel to unpack. Since they're groups of threes, they'll either start on the index, or halfway. I've attached my very legible diagram to explain it further.

    uint packedIndexPos = id.x * 3 / 2;
    if (id.x% 2 == 0)
    {
    uint2 indices = UnpackUShort2(IndexBuffer[packedIndexPos]);
    uint value1 = indices.x;
    uint value2 = indices.y;
    indices = UnpackUShort2(IndexBuffer[packedIndexPos + 1]);
    uint value3 = indices.x;
    }
    else
    {
    uint2 indices = UnpackUShort2(IndexBuffer[packedIndexPos]);
    uint value1 = indices.y;
    indices = UnpackUShort2(IndexBuffer[packedIndexPos + 1]);
    uint value2 = indices.x;
    uint value3 = indices.y;
    }

    To dispatch, use the amount of uint3's divided by the thread group size.
    computeShader.GetKernelThreadGroupSizes(0, out uint threadGroupSize, out _, out _);
    int groupCount = Mathf.CeilToInt((float)elementCount / threadGroupSize);
    computeShader.Dispatch(0, groupCount, 1, 1);
     

    Attached Files:

  3. unity_3KoGAU6lZHRhFA

    unity_3KoGAU6lZHRhFA

    Joined:
    Jul 26, 2022
    Posts:
    7
    Thomas-Mountainborn, Thank you so much for such an incredible detailed answer! As a contribution to your effort, i've made a polished version of that illustration if somebody finds it helpful:

    1.05.2023.14.53.3_crop_0.png

    i knew that shader receives ushorts as uints. int can hold exactly 2 shorts. but i thought maybe it possibly represents a single ushort as a single uint in shader. thank you for the clarification and code examples! they are incredibly valuable!

    when i get to implementing this, i will write here if there's something important to note.