例如,如果我想做灰度转换,我需要按以下方式设置我的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手动将每个块分配给每个线程组?
Metal 不知道也不关心你的着色器是否在图像上运行。它不会“切割”图像或类似的东西。
计算着色器通过“网格”进行处理。网格是一种抽象。这是您组织工作的任意方式。Metal 不会为网格赋予任何意义,例如将网格中的位置与图像中的像素相关联。
这种关联(如果存在)隐含在着色器代码的行为方式中。是的,这很大程度上取决于着色器对thread_position_in_grid、thread_position_in_threadgroup、thread_index_in_threadgroup等的作用。
因此,如果您使用gid具有该thread_position_in_grid属性的变量,并将其坐标用作图像坐标,则该用法指示每个网格位置对应于一个图像像素。一旦你这样做了,那么每个线程组都对应于图像的一个块,因为线程组只是一个网格位置块。不过,这又不是 Metal 正在做的事情,而是您的着色器正在做的事情。
你可以做一些完全不同的事情,金属不会在意。