例如,如果要进行灰度转换,则需要以以下方式设置我的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);
我知道图像将被切成不同的块,每个块将由一个线程组处理。但似乎在内核中,我们将只读取2d纹理,然后输出处理后的纹理。
但是问题是如何将图像切成不同的2d纹理?我们如何知道是否将每个图像块分配给一个线程进行处理?这是由Metal本身完成的吗?还是我们需要使用 gid 手动将每个块分配给每个线程组?
答案 0 :(得分:4)
金属不知道或不在乎您的着色器是否在图像上运行。它不会“砍”图像或类似的东西。
计算着色器通过“网格”进行处理。网格是一个抽象。这是您组织工作的任意方式。金属不会给网格赋予任何意义,例如将网格中的位置与图像中的像素相关联。
这种关联(如果存在)暗含在您的着色器代码的行为方式中。是的,这很大程度上取决于着色器对thread_position_in_grid
,thread_position_in_threadgroup
,thread_index_in_threadgroup
等的处理方式。
因此,如果您使用具有gid
属性的thread_position_in_grid
变量,并且将其坐标用作图像坐标,则使用率决定每个网格位置都对应一个图像像素。一旦执行此操作,则每个线程组都将对应于图像的一个块,因为线程组仅是网格位置的一个块。同样,这不是Metal要做的,而是您的着色器正在做的。
您可以做一些完全不同的事情,而Metal不在乎。