我正在制作一个统一的高度图侵蚀计算着色器,其中地图上的每个点分别被侵蚀。这对于小地图来说工作得很好,但我正在做的项目需要4096x4096的地图。这意味着需要模拟4096^2 = 16777216点。默认线程尺寸为[64,1,1],这将创建262144个线程组,远远超过允许的65535的限制。
我的问题是:
我可以简单地提高线程尺寸吗?当我这样做时,我必须考虑哪些性能方面的问题?是否有可能简单地运行着色器多次,不同范围的高度图坐标?
这是我第一次使用着色器。我在网上看到的教程很快就深入到gpu硬件规格,所以我没有从中学到太多。
使用每个工作组的64x64
线程,您可以Dispatch
64x64
工作组做您需要的事情:请记住,64x64
线程将为您调度的每个工作组调用,因此您将有64x64 work groups x 64x64 threads
=4096 workgroups x 4096 threads
执行。
computeShader.Dispatch(computeShader.FindKernel("kernel"), 64, 64, 1);
[numthreads(64, 64, 1)]
void kernel(uint3 id : SV_DispatchThreadID)
{
// ...
// 0 <= id.x < 4096
// 0 <= id.y < 4096
}
至于对性能的影响,一般的回答是"试试看!":使用不同大小的线程和工作组运行内核。结果可能因您的计算和硬件而异。
但是,如果您需要绕过65535
限制,您可以使用DispatchIndirect
。基本上,它与Dispatch
相同,但参数是通过ComputeBuffer传递的。
ComputeBuffer argsBuffer = new ComputeBuffer(3, sizeof(uint), ComputeBufferType.IndirectArguments);
uint[] args = { 64, 64, 1 }; // work groups
argsBuffer.SetData(args);
computeShader.DispatchIndirect(computeShader.FindKernel("kernel"), argsBuffer);
Ps:在GPU上工作需要理解它的架构,因为(1)你在一个较低的层次上工作,接近硬件,你工作的许多功能实际上是硬件实现的(例如纹理);(2)你想让你的程序获得最好的性能(例如,充分利用块,翘曲和缓存…);)