乐趣区

关于unity3d:Unity-关于ComputeShader中ThreadGroup和numthreads的理解

明天遇到一个神奇的景象,我设置了一个 100 * 100 的 texture,而后应用 ComputeShader 让它填充一些色彩,后果却有一个黑边。

代码如下所示:

_renderTexture = new RenderTexture(100, 100, 24);
        _renderTexture.enableRandomWrite = true;

_renderTexture.Create();
        
shader.Dispatch(0, _renderTexture.width / 8, _renderTexture.height / 8, 1);
[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{Result[id.xy] = float4(float3(id) / 100, 1);
}

最终咱们失去的图像是这样的,能够看到有个黑边。

我尝试了一下,如果我将 shader.Dispatch(0, _renderTexture.width / 8, _renderTexture.height / 8, 1); 中的 8 改为 9。

shader.Dispatch(0, _renderTexture.width / 9, _renderTexture.height / 9, 1);

就会发现,这条黑边,变得更加宽了。

通过我查阅相干文档后,我了解了一下 Dispatch 办法的三个参数是说在 XYZ 三个方向上划分多少个线程组。回到之前的 8。也就是划分了 100 / 8 = 12.5 -> 12 个线程组。

也就是说 100*100 的图像被横竖各划分了 12 次,有 12*12 个小格子,每个格子由一个线程组来执行。

然而 100 除以 8 不是整除,因而会多出一些像素未能调配到线程组中。因而呈现了黑边的状况。

如下图所示,这个图像是 100×100,每个红色的小格子是 8 ×8,横竖各有 12 个小格子,在最左边和最下边有一些蓝色的区域,无奈被线程组笼罩,这就是黑边产生的起因。

在 computeShader 代码中 [numthreads(8,8,1)] 相当于规定了每个线程组有多少个线程。如果咱们将 numthreads 中的 8 改为 9,黑边即可解决。

再来想一想,为什么 Dispatch 时,如果填入 9 黑边会变得更加大呢?

如下图所示

红色的格子是线程组,大小是 9*9,整个宽度是 100*100,因而横竖各有 11 个红色的格子,最初空蓝色的一条边。这条蓝色的边是线程组未指派的地带。

红色的格子是线程组里的线程数量是 8*8 它不能笼罩整个线程组的工作区域,因而它只能实现该区域的局部工作,而剩下的工作会由第二个线程组里的线程帮忙实现,这里是很奇怪,然而能够解释黑边变宽的起因。

红色的格子程度方向是 11 个,能够看到左边空出一块区域和蓝色的区域一起形成了黑边(无奈解决的区域)。

我将图画完,仿佛会造成这样的情况。

剩下红色的区域和蓝色的区域则是无奈解决的黑边。

这里就发现了它的一个个性:某个线程组实现不了的工作,会由其它的线程组里的线程顶替实现。 我不确定我这个了解是否正确,但事实看起来是如此。

如果我将 numthread 设置为 9*9,依照当初的了解,应该会产生一条蓝色区域这样的黑边。

退出移动版