ComputeShader: Accessing array elements within a StructuredBuffer

I have been toying with ComputeShaders for a while now, and have been trying to use them to leverage the hair physics calculations I was doing in my game. The hair is based off a series of points that use springs to create hair. Each strand is a list of these points.

I had success moving the physics code into a compute shader for one strand, and would be able to calculate 10,000 hair bodies at solid 60fps on one strand, but multiple strands would crash performance.

So I need to instead run a threadgroup for each hair strand, and dispatch these hair strands x amount of times. So I make a structure of hair strands, fill it with a max-sized array of ‘hair body’ structs. I would then access the hair strand by the groupID, and the hair bodies by the thread index.

Theoretically this should work, but I am not having these results. Due to limitations with StrucuredBuffer element sizes being max 2048 bytes, I can only store certain lengths of hair bodies per strand. When I try to change these values and read them from my C# script, they are null.

I have provided a test scenario that should duplicate my problem. I have simplified this only to get the base functionality working, which is setting the indexes of the array within the hair strand. The code is below:

ShaderTest.cs:

public class ShaderTest : MonoBehaviour
{
    public struct TestStruct1
    {
        public int groupID;
        public int[] threadIDs;
    }

    public ComputeShader computeShader;
    private ComputeBuffer computeBuffer;
    private int kernelID;

    void Start()
    {
        var stopWatch = new System.Diagnostics.Stopwatch();
        TestStruct1[] data = new TestStruct1[256];

        for (int i = 0; i < 256; i++)
        {
            TestStruct1 s1 = data*;*

s1.threadIDs = new int[50];
}

this.kernelID = computeShader.FindKernel(“CSMain”);
computeBuffer = new ComputeBuffer(256, sizeof(int) + (50 * sizeof(int)));
computeBuffer.SetData(data);
computeShader.SetBuffer(kernelID, “Buf”, computeBuffer);
stopWatch.Start();
computeShader.Dispatch(kernelID, 256, 1, 1);

computeBuffer.GetData(data);

stopWatch.Stop();

Debug.Log(“Took: " + stopWatch.ElapsedMilliseconds + " milliseconds to compute”);
foreach(TestStruct1 d in data)
{
Debug.Log(d.threadIDs[0]); // Crashes here
}

computeBuffer.Release();
}
}
ShaderTest.compute:
#pragma kernel CSMain

struct TestStruct1
{

  • int groupID;*
  • int threadIDs[50];*
    };

RWStructuredBuffer Buf;

[numthreads(64,1,1)]
void CSMain(int3 threadID : SV_GroupThreadID, int3 groupID : SV_GroupID)
{

  • if (threadID.x <= 50)*
  • {*
  •  Buf[groupID.x].threadIDs[threadID.x] = 7;*
    
  • } *
    }
    All I am trying to do in the above code is properly index through the buffer and set each threadID to 7 for proof that this structure works. For whatever reason, it is not giving me the expected results that were so clear before.
    Any help would be greatly appreciated

hey i am having same problem at using struct containing array in it.
just curious, did you solve this problem???