Metal如何将图像块分配到每个线程组?

Fra*_*Joe 2 metal

在此输入图像描述 在此输入图像描述

例如,如果我想做灰度转换,我需要按以下方式设置我的threadsPerGroup和线程组。

NSUInteger maxTotalThreadsPerThreadgroup = [self.computePipelineState maxTotalThreadsPerThreadgroup];
MTLSize threadgroupCounts = MTLSizeMake(threadExecutionWidth * 2, threadExecutionWidth * 2, 1);
MTLSize threadsPerThreadGroup = MTLSizeMake([self.texutre width] / threadgroupCounts.width + 1,
[self.texutre height] / threadgroupCounts.height + 1,
1);
Run Code Online (Sandbox Code Playgroud)

我知道图像将被切成不同的块,每个块将由一个线程组处理。但在内核中,我们似乎只是读取2d纹理,然后输出处理后的纹理。

但问题是如何将图像切割成不同的 2d 纹理?我们如何知道每个图像块是否分配给一个线程来处理?这是 Metal 自己做的吗?或者我们需要使用gid手动将每个块分配给每个线程组?

Ken*_*ses 5

Metal 不知道也不关心你的着色器是否在图像上运行。它不会“切割”图像或类似的东西。

计算着色器通过“网格”进行处理。网格是一种抽象。这是您组织工作的任意方式。Metal 不会为网格赋予任何意义,例如将网格中的位置与图像中的像素相关联。

这种关联(如果存在)隐含在着色器代码的行为方式中。是的,这很大程度上取决于着色器对thread_position_in_gridthread_position_in_threadgroupthread_index_in_threadgroup等的作用。

因此,如果您使用gid具有该thread_position_in_grid属性的变量,并将其坐标用作图像坐标,则该用法指示每个网格位置对应于一个图像像素。一旦你这样做了,那么每个线程组都对应于图像的一个块,因为线程组只是一个网格位置块。不过,这又不是 Metal 正在做的事情,而是您的着色器正在做的事情。

你可以做一些完全不同的事情,金属不会在意。