Ios 在金属计算内核中访问网格位置以外的像素?

Ios 在金属计算内核中访问网格位置以外的像素?,ios,shader,metal,compute-shader,Ios,Shader,Metal,Compute Shader,我有一个金属内核函数。通常,您访问的像素如下所示: kernel void edgeDetect(texture2d<half, access::sample> inTexture [[ texture(0) ]], texture2d<half, access::write> outTexture [[ texture(1) ]], device const uint *roi [[ buf

我有一个金属内核函数。通常,您访问的像素如下所示:

kernel void edgeDetect(texture2d<half, access::sample> inTexture [[ texture(0) ]],
                    texture2d<half, access::write> outTexture [[ texture(1) ]],
                    device const uint *roi [[ buffer(0) ]],
                    uint2 grid [[ thread_position_in_grid ]]) {

  if (grid.x >= outTexture.get_width() || grid.y >= outTexture.get_height()) {
      return;
  }

  half c[9];
  for (int i=0; i < 3; ++i) {
    for (int j=0; j < 3; ++j) {
      c[3*i+j] = inTexture.read(grid + uint2(i-1,j-1)).x;
    }
  }

  half3 Lx = 2.0*(c[7]-c[1]) + c[6] + c[8] - c[2] - c[0];
  half3 Ly = 2.0*(c[3]-c[5]) + c[6] + c[0] - c[2] - c[8];
  half3 G = sqrt(Lx*Lx+Ly*Ly);

  outTexture.write(half4(G, 0.0), grid);
}
      half4 inColor = inTexture.read(grid - uint2(-1,-1));
基本上这是可行的,但在螺纹边界上我有“不连续”,如图所示(砖墙图案)

这是很清楚的,因为每个线程只传递它的子纹理来处理。因此,超出线程边界,我无法访问像素


我的问题是:当我需要在计算内核中处理超出当前位置的像素时,概念是什么?这在计算内核中可能吗?

我发现了一个问题:

线路

c[3*i+j] = inTexture.read(grid + uint2(i-1,j-1)).x;
必须更改为:

c[3*i+j] = inTexture.read(grid + uint2(i,j)).x;

很明显,纹理中的-1位置索引失败,产生了上图所示的砖墙状人工制品。

我发现了问题:

线路

c[3*i+j] = inTexture.read(grid + uint2(i-1,j-1)).x;
必须更改为:

c[3*i+j] = inTexture.read(grid + uint2(i,j)).x;

很明显,纹理中的位置索引-1失败,产生了上图中所示的砖墙状人工制品。

为了确保有人将其作为答案附加到该注释中:在计算着色器中可以访问的像素没有限制。网格大小仅影响调度

您的错误是实例化带有负数的无符号
uint2
。在循环的第一次迭代中,您将尝试构造
uint2(-1,-1)
,它与
uint2(4294967295,4294967295)
相同,因此是越界的


您可以使用
int2
,或者根据您的自我回答,只需避免使用负数即可。

为了确保有人将其作为答案附加到此注释中:您可以在计算着色器中访问哪些像素没有限制。网格大小仅影响调度

您的错误是实例化带有负数的无符号
uint2
。在循环的第一次迭代中,您将尝试构造
uint2(-1,-1)
,它与
uint2(4294967295,4294967295)
相同,因此是越界的


您可以使用
int2
,或者根据您的自我回答,避免使用负数。

我不太明白您所说的“这很清楚,因为每个线程只传递它的子纹理进行处理”。您是否可以充实不起作用的示例代码,并提供一些排队参数?考虑到你发布的代码,我一点也不清楚你是如何得到所提供的图像的-似乎缺少了很多步骤,我不相信问题出在你认为的地方。我已经添加了实际运行的代码!它是以线程组(32,16,1)和每个线程组适当数量的线程进行线程处理的。我真的不明白你所说的“这很清楚,因为每个线程只传递它的子纹理进行处理”是什么意思。你能否充实出不起作用的示例代码,并提供一些排队参数?考虑到你发布的代码,我一点也不清楚你是如何得到所提供的图像的-似乎缺少了很多步骤,我不相信问题出在你认为的地方。我已经添加了实际运行的代码!它以(32,16,1)的螺纹组进行螺纹连接,每个螺纹组有适当数量的螺纹。