0
\$\begingroup\$

I'm trying to move a 262,144 [2^18] points (stars) in a compute shader and am struggling to reliably address the data in a buffer.

I understand that there's a 3-dimensional array SV_DispatchThreadID that provides an index for the thread in the thread group.

My hardware can run 65,536 threads per thread group (assuming I've understood the terminology correctly). As my total number of stars exceeds that number (and they're rendered), unity must be making multiple calls under the covers(?)

In any case, I have:

[numthreads(64, 64, 16)]
void BuildStars(uint3 id3 : SV_DispatchThreadID, uint id1 : SV_GroupIndex) {
    int id = id3.x 
            + id3.y * 64
            + id3.z * 4096;
    ...

[To simplify things, I'm only attempting to use 32,768 stars to begin with, meaning I'm ignoring id1 for the moment. I'd hoped to be able to add id += id1 * 65536, but I haven't got that far yet]

The movement of the stars is inconsistent. Some move far more rapidly than others, some don't move at all.

As all I'm doing is adding a constant offset every frame, the only explanation I can come up with is that I'm generating the ID incorrectly, wrapping around and effectively updating random stars

mapComputeShader.Dispatch(Kernel("MoveStars"), 64, 64, 8);

With an eye to calling the following in future

mapComputeShader.Dispatch(Kernel("MoveStars"), 64, 64, 64);

What's the correct way from within the compute shader to get an id that varies from 0 to numDispatchedThreads - 1, where numDispatchedThreads exceeds 65,536?

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Well first of all, the way GPUs work is each warp or compute block will have to make a product of 1024, so numthreads(1024,1,1) will do, 64 * 64 * 16 or numthreads(64,64,16) isn't valid. Think of the numthreads term as a way of distributing a collection of threads in the GPU. you can have numthreads(4,1,1) which is 4 compute blocks working all at the same time or you can have numthreads(2,2,1) which is the same 4 compute blocks still working at the same time but instead of having an index of X, you have XY. Usually for texture work you see XY style thread groups since that is conceptually what is best for the given task (this can sometimes tell the engine how to structure the memory differently but for the most part it just comes down to the work done to get the index.) Unity can in fact schedule groups of work but the group blocks are a little different in how you call dispatch. if you have a 128x128 image and you queue (32,32,1) then the dispatch terms should be ceil(128/32), ceil(128/32), ceil(128/1) or

mapComputeShader.Dispatch(kernel, 4, 4, 1);

the documentation on what indexing systems you have at hand and some other useful documentation files are here:

Also heavy side note, have an if statement at the top of your compute shader to stop the index if it goes past your array, it will keep working past the buffer if you let it,

\$\endgroup\$
4
  • \$\begingroup\$ Thanks for that. I don't care about "using" the dimensions, I just need the number of threads, so 1024/1/1 would be fine. That said, I need to run that several hundred times, accessing different parts of the buffer every time. 1024 threads per warp isn't an issue. Being unable to get the warp ID is (otherwise I'll be re-addressing the first 1024 every time). \$\endgroup\$
    – Basic
    Commented Nov 8, 2022 at 11:19
  • \$\begingroup\$ @Basic From a quick test, you can address the buffer past 1024 indices by using SV_DispatchThreadID. If you were to have numthreads(1024,1,1) and dispatch (4,1,1) equating to 4096 elements processed, it would index out from 0 - 4095 \$\endgroup\$ Commented Nov 8, 2022 at 14:52
  • \$\begingroup\$ Okay, I think you've just thrown light on a key detail I was missing. Just to confirm: If I have numthreads(1024, 1, 1) in the shader and call Dispatch(kernel, 8, 1, 1) from Unity, I will get a total of 8192 executions, with a thread ID x component that varies from 0 to 8191? \$\endgroup\$
    – Basic
    Commented Nov 9, 2022 at 2:24
  • \$\begingroup\$ @Basic That is correct my friend! id.x will go from 0-8191 in that dispatch. \$\endgroup\$ Commented Nov 9, 2022 at 21:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .