Unity ComputeShader笔记
#pragma kernel CSMain //定义核心函数 RWTexture2D<float4> Result;//这声明了一个变量,它包含的数据是shader程序将要用到的。我们不需要用到网格mesh数据,你需要像这样明确的声明,你的compute shader需要写入读出什么数据。数据类型名前面的“RW”指定了shader可以进行读写操作。 [numthreads(8,8,1)]//指定线程组的大小为一个(8*8*1)的三维数组。Tips:这个三维数组最大值不超过1024 void CSMain (uint3 id : SV_DispatchThreadID) { Result[id.xy] = float4(id.x & id.y, (id.x & 15)/15.0, (id.y & 15)/15.0, 0.0); }
C#代码
public ComputeShader shader; void RunShader() { int kernelHandle = shader.FindKernel("CSMain"); RenderTexture tex = new RenderTexture(256,256,24); tex.enableRandomWrite = true; tex.Create(); shader.SetTexture(kernelHandle, "Result", tex); shader.Dispatch(kernelHandle, 256/8, 256/8, 1); }
Dispatch (x, y, z) 与 numthreads (x, y, z) 的关系
Dispatch(x, y, z)是一个放置线程组的三维数组,numthreads(x, y, z)是一个放置线程的三维数组(就是前面所提的线程组)
如果你的GPU又64个核心,你的Dispatch(x, y, z)总长度恰好是64,那么每个核心将处理一个线程组。
单个线程组长度在不同硬件厂下分配的资源是不同的所以建议:AMD单个线程组长度使用64的倍数(wavefront架构),NVIDIA单个线程组长度使用32的倍数(SIMD32(Warp)架构)。所以为了保证兼容性最后单个线程组长度最好为32的倍数。
SV_GroupID、SV_GroupThreadID、SV_GroupIndex、SV_DispatchThreadID
SV_GroupID : 线程组 ID(三維,线程组的三维坐标)
SV_GroupThreadID : 线程组内线程ID (三維,线程在线程组内的三维坐标)
SV_GroupIndex : 线程在线程组内的下标(一维)
SV_DispatchThreadID : 唯一ID (可以理解为在图片上的坐标)
计算:
SV_GroupID = Dispatch(x,y,z)中的坐标位置
SV_GroupThreadID = numthreads(x, y, z)中的坐标位置
SV_GroupIndex = z*numthreads(x, y, z).x*numthreads(x, y, z).y + y*numthreads(x, y, z).x + x
SV_DispatchThreadID = (SV_GroupID.x*numthreads(x, y, z).x+SV_GroupThreadID.x,SV_GroupID.y*numthreads(x, y, z).y+SV_GroupThreadID.y+SV_GroupID.z*numthreads(x, y, z).z+SV_GroupThreadID.z)