如何在 Swift 和 Metal 之间的桥接标头中使用“packed_float3”?

How can I use `packed_float3` in a bridging header between Swift and Metal?

提问人:Matt Bierner 提问时间:10/28/2023 更新时间:10/28/2023 访问量:29

问:

我需要将一个带有 () 值的结构从 Swift 传递到我的 Metal 着色器中。我目前正在使用桥接标头在 Swift 和 metal 之间共享类型。这是我尝试编写的结构:packed_float3MTLPackedFloat3

typedef struct {
    packed_float3 value;
} CustomData;

但是,当我尝试使用 时,出现以下错误:packed_float3

unknown type name 'packed_float3'

我尝试了各种类型变体,包括 、 、 、 ,但它们都不起作用。我还尝试过包含各种其他标头,例如 or,但这通常会产生其他编译器错误MTLPackedFloat3packed_simd_float3metal::packed_float3vector_packed_float3packed<float, 3><metal/metal.h><metal/MTLAccelerationStructureTypes.h>

如何在桥接标头中使用打包值,而无需定义自己的类型?

iOS 版Swift Metal

评论

1赞 Martin R 10/28/2023
Swift 论坛上的相关讨论:forums.swift.org/t/no-simd-packed-float3-in-swift/61227

答:

0赞 Matt Bierner 10/28/2023 #1

可能有更好的方法可以做到这一点,但这里对我有用:

我认为根本原因是桥接头基本上是在两种不同的环境中“构建”了两次:一次是 Swift,一次是 Metal。 例如,总是在 Metal 中定义,但在 Swift 中未定义。另一方面,在 Swift 中工作正常,在 Metal 中没有定义。packed_float3MTLPackedFloat3

作为一种解决方法,我们可以使用预处理来改变 Metal 编译和 swift 编译中使用的类型。执行此操作的一种简单方法是检查是否已定义,因为只有当标头包含在 Metal 中时才会定义。现在对于 Swift,我们可以别名为 Swift 类型:__METAL_VERSION__packed_float3MTLPackedFloat3

#ifndef __METAL_VERSION__
#include <metal/metal.h>
typedef MTLPackedFloat3 packed_float3;
#endif

此代码仅在 Swift 编译中处于活动状态。它还依赖于并具有相同的数据布局。现在,您可以在 Swift 和 Metal 的标题中使用!MTLPackedFloat3packed_float3packed_float3

有兴趣听听是否有更好的方法,因为这很丑陋

评论

0赞 Spo1ler 10/28/2023
我的意思是,你可以直接定义它在金属中定义的方式packed_float3typedef __attribute__((__packed_vector_type__(3))) float packed_float3;
0赞 Matt Bierner 10/28/2023
如果您尝试使用它,则会出现警告和错误:unknown attribute '__packed_vector_type__' ignoredMTLPackedFloat3Cannot convert value of type 'MTLPackedFloat3' (aka '_MTLPackedFloat3') to expected argument type 'packed_float3' (aka 'Float')
0赞 Spo1ler 10/28/2023
事实上,我检查了一下,我自己定义了typedef struct __attribute__((packed)) packed_float3 { float x; float y; float z; } packed_float3;
0赞 Spo1ler 10/28/2023
需要注意的是,它们是布局兼容的,但显然从编译器的角度来看,它们是不同的类型。