Joshua Favorite
Joshua Favorite

Reputation: 36

For a very niche project: how to pass a C# class to a Compute Shader and get out multiple 2d float arrays

I'll do my best to explain the problem, which first requires an explanation of the project. I apologize ahead of time if it's a bit scattered. I have ADHD, which has made communicating on this platform massively difficult, so please bear with me. This is necessary to mention because stack overflow has consistently suppressed my questions for being scattered and I'm tired of this intolerance.

The project generates a 3D Worley noise map using my own unoptimized algorithm, which, at the moment, requires iterating through every index of the 3D array and individually calculating every element's value on the CPU one at a time. also, this will be in 3D world space.

Additionally, I needed to write my own class for the randomized points or "nodes" because this program iteratively moves these nodes in pseudorandom directions, and each node is associated with a procedure for calculating map index values, which is just assigned via an integer between 1 and 6. after each iteration, the map is regenerated. Without the nodes, this can't work. Code for the Nodes on repl.it

Obviously, this is extremely slow, and I need to implement multithreading and compute shaders, which is the conclusion I've come to. Still, I'm faced with a massive problem: I've no idea how to use hlsl or compute shaders, and I cannot, for the life of me, find any resources on hlsl for C#/java/python programmers that would help me wrap my head around anything. ANY resources explaining hlsl on a basic level would be enormously helpful.

Now, for the specific problem of this question: I have no idea how to start. I have one vague idea of an approach that is derived from my ignorance about multithreading. I could use 32 individual 32x32 RWStructuredTexture2D<float> arrays that I stack after calling my shader to create a 3D texture; however, to do this, I need to be able to pass my nodes to the shader, and every use of compute shaders I've seen only has one parameter, uint3 id : SV_DispatchThreadID, which makes no sense to me. I've briefly considered making a struct for the nodes in my shader, but I still have no idea how to get that information to my shader.

For the actual question: how do I throw nodes at this and then get 32 32x32 float arrays out of it? here's some pseudocode for the in-betweens.

//somehow set this up to have 32 different threads
//make an hlsl equivalent of a float[,]
@params NodeSet nodes and z coordinate
@return float[32,32]
//NodeSet is just a collection of Nodes that has some convenience methods.
float[,] CSMain(@params) {
   for(int x = 0; x < 32; x++)
      for(int y = 0; y < 32; y++)
         //set value of element
   return floatArr;
}

Second question: should I even be using Compute Shaders for this problem?

Upvotes: 1

Views: 376

Answers (1)

Ruzihm
Ruzihm

Reputation: 20270

You should use 32 x 32 x 32 threads and output to a 1d buffer of length 32 x 32 x 32 based on the id of the thread

Pseudocode:

#pragma kernel PseudoCode

[numthreads(32, 32, 32)]
void PseudoCode (uint3 id : SV_DispatchThreadID) {
    float3 pos = id; // or id - float3(15.5,15.5,15.5) to center, etc.
    int outputIndex = id.x*32*32+id.y*32+id.z;
    for (int i = 0; i < nodecount ; i++)
        outputbuffer[outputIndex] += GetInfluence(nodeData[i], pos);

    outputBuffer[outputIndex] = NormalizeOutput(outputBuffer[outputIndex]);
}

Upvotes: 0

Related Questions