共计 1290 个字符,预计需要花费 4 分钟才能阅读完成。
明天遇到一个神奇的景象,我设置了一个 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
,依照当初的了解,应该会产生一条蓝色区域这样的黑边。