内核中的像素坐标,纹理坐标和Gid

Unh*_*lig 5 metal

假设我有一个100宽度和100高度大小的纹理,并以{10, 10, 1}线程组和大小将其分派给内核函数。

我很难理解是thread_position_in_grid从0-9还是从0-99(因为我的纹理的大小是100 x 100)?

我使用的float4 c = in.read(gid);检索质感的颜色,但我想知道如何gid映射到纹理坐标检索结果这类型的float4(会有它在哪里像素(纹理之间的情况?)坐标?)。

我想深入了解以上内容的工作原理,因为我想要实现的是能够检索内核函数中纹理大小所定义的确切位置;即:

调度大小:{10, 10, 1}和纹理大小100 x 100;并在内核函数中检索值:

0、1、2、3、4、5 ...,99。

综上所述,如何gidtexture coordinates以及pixel coordinates内核函数内有关?它们如何从一个映射到另一个?在过去的4天里,我一直在阅读文档和类似的问题,但是我并没有成功获得具体而权威的答案。

谢谢。

war*_*enm 5

在您的示例中,您正在分派这样的工作网格:

MTLSize threadsPerThreadgroup = { 10, 10, 1 };
MTLSize threadgroupCount = { 10, 10, 1 };
[computeEncoder dispatchThreadgroups:threadgroupCount
               threadsPerThreadgroup:threadsPerThreadgroup];
Run Code Online (Sandbox Code Playgroud)

您的gid具有属性thread_position_in_grid,可能是类型uint2,因为网格的域是二维的。到目前为止,一切都很好。

gid范围为(0,0)至(99,99)。如何将其映射到其他数量(包括纹理坐标)完全取决于您

例如,假设您不是在100x100纹理上运行,而是在300x300纹理上运行,而您想在右下角执行一些操作。在这种情况下,您可以添加uint2(200, 200)gid读前/写纹理,以解决像素的区域坐标为(200,200)(299,299)。其他任意转换也是尽可能的。

基本上,指定网格尺寸是一种方便的方式,可以用来描述您要执行的操作的逻辑形状,同时(通过threadsPerThreadgroup)还可以使您优化可以并行执行的工作量。

至于(规范化的)纹理坐标,在网格尺寸与纹理尺寸完全匹配的简单情况下,您可以通过除以该[[threads_per_grid]]属性限定的参数来获得与内核函数调用相对应的规范化坐标,记住先进行转换避免被截断:

float2 coords = gid / float2(tpg)
Run Code Online (Sandbox Code Playgroud)

这里tpg是另一个参数到你的内核函数声明为uint2 tpg [[threads_per_grid]]

  • 当从纹理中*采样*时,有关归一化纹理坐标的位是正确的(例如,使用`in.sample(in_sampler,coords,...)`)。当像原始问题中那样*读取*纹理时,该纹理始终使用非规范化纹理(也称为texel或像素)坐标。明确说明其他一些问题:网格位置和纹理坐标之间不涉及自动转换;您传递的值将直接解释为纹理坐标。阅读时,没有“中间”的纹理坐标。您将传递整数,并且这些整数将一对一映射到纹理坐标。 (2认同)
  • @Unheilig:除非*您*决定将它们关联起来,否则网格尺寸与纹理尺寸**完全无关**。而且,如果你这样做了,那么你可以通过你在代码中所做的事情来控制它们的关系。网格尺寸完全取决于您传递给 `-dispatchThreadgroups:threadsPerThreadgroup:` 的内容。当然,纹理尺寸是纹理的一个属性。写出你对 `gid` 的困惑:它既不是 0-99 也不是 0-9999。它是二维的;它从 (0,0) 到 (99,99)。`tpg` 将是 (99,99),这就是为什么除以它会将 `coords` 规范化为 (0.0,0.0) 到 (1.0,1.0)。 (2认同)
  • @Unheilig:计算函数是通用的;它们并不特定于图像处理。因此,它们与纹理或尺寸等无关。你真的需要打破你不断想象它们是相关的心理固着。网格是一种划分工作的抽象方式。您可以按照对您和工作性质有意义的任何方式来划分工作。是的,使用计算函数进行图像处理是“可能”的。不管怎样,我不知道你从哪里得到“(9999,9999)”。我们所讨论的内容中没有任何内容具有这些维度。 (2认同)
  • 具有属性“thread_position_in_grid”的函数输入(您命名为“gid”)与线程组无关。它是相对于整个网格的。如果要将其从二维坐标转换为线性索引,可以执行`uint index = gid.y * tpg.x + gid.x;`。这在概念上是“thisRow * rowWidth + thisColumn”。 (2认同)