金属质感的右边缘有异常

问题描述 投票:0回答:2

[当我在Macbook Pro的集成英特尔GPU上运行此代码时,我没有问题。但是,当我在带有AMD GPU的iMac上运行它时,这个简单的“ Hello World”在右侧显示了工件:

enter image description here

着色器非常简单:

kernel void helloworld(texture2d<float, access::write> outTexture [[texture(0)]],
                     uint2 gid [[thread_position_in_grid]])
{
    outTexture.write(float4((float)gid.x/640,
                            (float)gid.y/360,0,1),
                     gid);
}

我已经尝试以两种不同的方式查看纹理的内容,并且都产生了问题:

将纹理转换为CIImage并在NSImageView中查看,或调用getBytes并直接复制像素数据并手动从中手动构建PNG(完全跳过CIImage)。两种方法都会产生这种奇怪的伪像,因此确实存在于纹理本身中。

任何想法导致这种问题的原因?

更新:

令人着迷,问题似乎与threadsPerThreadgroup有关,但我不确定为什么会这样。

上面的图像是每组24个线程创建的。如果将其更改为16,则伪像将移至底部边缘。

对此我不了解的是,无论实际正在运行哪个线程组,都应该固定gid位置,不是吗?因为那是整个图像中各个线程的位置。

gpu metal
2个回答
0
投票

使用macOS 10.13或更高版本,可以让OS弄清其中的一些问题。我正在使用:

commandEncoder.dispatchThreadgroups(threadgroupsPerGrid, threadsPerThreadgroup: threadsPerThreadgroup)

这样做,我必须自己计算threadgroupsPerGrid,这被证明是问题的根源。

通过将此呼叫替换为:

commandEncoder.dispatchThreads(MTLSize(width: Int(width), height: Int(height), depth: 1), threadsPerThreadgroup: threadsPerThreadgroup)

问题消失了。


0
投票

使用dispatchThreadgroups(),可以为宽度*高度网格之外的网格位置调用计算内核。您必须明确地不执行任何操作,例如:

if (gid.x >= 640 || gid.y >= 360)
    return;

否则,您将尝试在纹理的边界之外书写(使用某些分量大于1的颜色)。结果不确定。

使用dispatchThreads(),Metal会为您处理这件事,并且不会在您指定的网格大小之外调用。

[每组24和16个线程之间的行为差​​异在于,是否将其平均划分为640和360。无论是哪个均分,都是过度调用的维。

© www.soinside.com 2019 - 2024. All rights reserved.