Understanding of Buffer index in compute shader

Viewed 43

compute shader script:

#pragma kernel CSMain
RWStructuredBuffer<int> result;
 
[numthreads(8, 8, 8)]
void CSMain(int id : SV_DispatchThreadID )
{
    result[id] = id;
}

c# script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ForTesting : MonoBehaviour
{
    public ComputeShader compute;
 
    // Use this for initialization
    void Start()
    {
        ComputeBuffer resultBuffer = new ComputeBuffer(8*8*8, sizeof(int));
     
        var kernel = compute.FindKernel("CSMain");
        compute.SetBuffer(kernel, "result", resultBuffer);
        compute.Dispatch(kernel,1,1,1);
 
        int[] result = new int[8 * 8 * 8];
        resultBuffer.GetData(result);
   
        resultBuffer.Release();
    }
}

These are testing code for what value is in a result. I don't understand result[id] = id; line.

Exactly, result[id]. Accessing with index to buffer.

And while google, I saw a post saying that the shader function is executed as many as the number of threads.

Then in above case, cause numthreads(8, 8, 8) and Dispatch(kernel, 1, 1, 1), Does CSMain function run 8 * 8 * 8 * 1 * 1 * 1 times?

1 Answers

Firstly result[id] = id; is not type safe. id has three int components but the index to result and the value of result is just an int. So what's really happening is just the first component is being used i.e. result[id.x] = id.x;

Edit: I should have said int id : SV_DispatchThreadID is not type safe, it should be uint3 id : SV_DispatchThreadID as SV_DispatchThreadID has three components.

You can access the second and third elements by id.y and id.z.


You can think of the compute shader as a for loop

void kernel(int[3] id)
{
    ...
}

List<int[3]> ids;

for (var id : ids)
    kernel(id);

except each call to the kernel is executed in parallel not sequentially.


You should read the documentation here to understand how List<int[3]> ids; i.e. SV_DispatchThreadID are calculated

In your specific case:

var iota = Enumerable.Range(0, 8);
List<int[3]> ids = cartesian_product(iota, iota, iota);

where ids has size/length 8*8*8;

Related