gpu - 金属质感的右边缘有异常
问题描述
当我在 Macbook Pro 上的集成英特尔 GPU 上运行此代码时,我没有任何问题。但是当我在带有 AMD GPU 的 iMac 上运行它时,这个简单的“Hello World”给了我右边缘的伪像:
着色器非常简单:
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
无论实际运行的是什么线程组,都应该固定位置,不是吗?因为那是整个图像中各个线程的位置。
解决方案
使用dispatchThreadgroups()
,可以为宽度*高度网格之外的网格位置调用计算内核。您必须明确地不执行以下操作:
if (gid.x >= 640 || gid.y >= 360)
return;
否则,您将尝试在纹理边界之外写入(使用其中一些分量大于 1 的颜色)。这有未定义的结果。
使用dispatchThreads()
,Metal 会为您处理此问题,并且不会在您指定的网格大小之外调用。
每组 24 和 16 个线程之间的行为差异在于它是否均匀地划分为 640 和 360。不均匀地划分的是被过度调用的维度。
推荐阅读
- javascript - 如何制作 mydomain.com/someID 类型的 URL,其中 someID 来自 firestore 中的字段(doc)?
- redis - Redis LRANGE 流行原子性
- php - mediawiki 扩展中的原始 HTML
- android - StateFlow 上的 Jetpack Compose collectAsState 返回 null
- python - 如何遍历 csv 行以从 URLS 中提取文本
- python - 尝试获取 url 结尾时出现 Discord Py AttributeError
- sql - PostgreSQL 数据库分区没有按我的预期工作
- javascript - JavaScript 只是没有返回正确的长度
- java - apache骆驼文件从sftp下载到本地目录。我收到此错误:com.jcraft.jsch.SftpException:没有这样的文件
- reactjs - 修改 Ant Design (antd) 时间选择器页脚文本