繁体   English   中英

在金属计算内核着色器中,thread_position_in_grid到底意味着什么?

[英]What exactly does thread_position_in_grid mean in a metal compute kernel shader?

尽管这是对计算着色器的不当使用,但我仍在进行一些实验来确定是否可以使用它来生成一般的UV渐变,其中图像的一个通道从x轴沿0-1线性移动,另一个通道从x沿线性移动。图像的y轴上为0-1。 但是,当我通过用thread_position_in_grid.x值除以图像宽度来改变纹理的b值来生成此图像时,我感到困惑。 我在thread_position_in_grid位置编辑了纹理的像素:

在此处输入图片说明

是的,它是一个渐变,但它肯定不是我想要的从0-1开始的渐变。 我将其放到图像编辑器中,并且确定它不是线性的。 (下面添加的部分显示了从0-1开始的线性渐变的样子)

在此处输入图片说明

看来我不明白th​​read_position_in_grid值的确切含义。 我知道这与每个线程组的线程数和线程执行宽度有关,但我不完全了解。 我想我的最终目标是知道是否可以在计算着色器中生成下面的渐变,但是我不知道发生了什么。

在此处输入图片说明

作为参考,我正在使用具有以下线程设置的100x100纹理。 确实我不知道为什么使用这些值,但这是我在某处看到的建议,因此我坚持使用它们。 我希望能够将此问题推广到其他纹理尺寸以及矩形。

let w = greenPipeline.threadExecutionWidth
let h = greenPipeline.maxTotalThreadsPerThreadgroup / w
let threadsPerThreadgroup = MTLSizeMake(w, h, 1)
let threadgroupsPerGrid = MTLSize(width: (texture.width + w - 1) / w,
                                  height: (texture.height + h - 1) / h,
                                  depth: 1)
encoder.dispatchThreadgroups(threadgroupsPerGrid, threadsPerThreadgroup: threadsPerThreadgroup)

我的着色器看起来像这样:

kernel void green(texture2d<float, access::write> outputTexture [[texture(0)]],
                             uint2 position [[thread_position_in_grid]])
{
    if (position.x >= outputTexture.get_width() || position.y >= outputTexture.get_height()) {
        return;
    }
    outputTexture.write(float4(position.x / 100.0, 0.0, 0.0, 0.0), position);
}

关于此着色器的两件事使我感到困惑,因为我无法解释它们:

  1. 我使用位置作为在纹理上写入的坐标,因此困扰我的是该位置无法生成渐变。
  2. 您不能用position.x / outputTexture.getWidth()替换position.x / 100.0值,即使它也应该是100。这样做会导致图像变黑。 但是,当我制作一个着色器时,使用outputTexture.getWidth()作为其值对所有内容着色,它确实确实将所有内容着色为等于100的值(或者由于四舍五入而更准确地为101)
  3. 可以使用position检查内核是否在范围之内,而不创建UV渐变。

到底是怎么回事?

thread_position_in_grid含义是您想要的含义,因为可以确定网格的大小以及网格中每个线程的作用。

在您的示例中, thread_position_in_grid是纹理中的像素坐标,因为网格大小等于纹理中的像素数(四舍五入为管道最大线程执行宽度的倍数)。

如果将threadGroupsPerGrid更改为:

let threadgroupsPerGrid = MTLSize(width: (texture.width/2 + w - 1) / w,
                                  height: (texture.height/2 + h - 1) / h,
                                  depth: 1)

现在,仅应填充纹理的前四分之一,因为网格仅覆盖纹理宽度和高度的一半。

至于为什么您的纹理看起来很怪异,这可能与像素格式有关。 毕竟,您正在写入红色分量,并且纹理显示为蓝色。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM