关于C#:是否缺少着色器C兼容性很重要?

Does lack of shader C compatibility matter?

我正在学习《 Metal与金属运行》,第2部分,试图学习使用最佳可用语言功能重写所有代码。这些功能之一是C构造函数,我很高兴能够在我的着色器中使用它,它来自Cg和GLSL,它们没有此功能。

此代码在设备上运行正常,但我收到警告:

'vertex_main' has C-linkage specified, but returns user-defined type
'ColoredVertex' which is incompatible with C

这重要吗?我不知道为什么要指定C链接。我也不知道如何禁用警告(这是我想做的事),以及在没有问题的情况下报告错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using namespace metal;

struct ColoredVertex {
    const float4 position [[position]];
    const half4 color;

    ColoredVertex(const float4 position, const half4 color)
    : position(position), color(color) {}
};

vertex ColoredVertex vertex_main(
    constant float4 *position [[buffer(0)]],
    constant float4 *color [[buffer(1)]],
    uint vid [[vertex_id]]
) {return ColoredVertex(position[vid], half4(color[vid]));}

fragment half4 fragment_main(ColoredVertex vert [[stage_in]]) {
    return vert.color;
}


让我们在您的Metal源代码中添加另一个功能:

1
int myFunction(int x) { return x / 2; }

然后让我们手动运行编译器,并要求其发出人类可读的格式:

1
xcrun -sdk iphoneos metal MyLibrary.metal -S -emit-llvm

输出在MyLibrary.ll中。这是输出中vertex_main的定义:

1
2
3
4
5
6
7
8
9
10
11
define %struct.ColoredVertex.packed @vertex_main(<4 x float> addrspace(2)* nocapture readonly, <4 x float> addrspace(2)* nocapture readonly, i32) local_unnamed_addr #1 {
  %4 = zext i32 %2 to i64
  %5 = getelementptr inbounds <4 x float>, <4 x float> addrspace(2)* %0, i64 %4
  %6 = load <4 x float>, <4 x float> addrspace(2)* %5, align 16, !tbaa !22
  %7 = getelementptr inbounds <4 x float>, <4 x float> addrspace(2)* %1, i64 %4
  %8 = load <4 x float>, <4 x float> addrspace(2)* %7, align 16, !tbaa !22
  %9 = tail call fast <4 x half> @air.convert.f.v4f16.f.v4f32(<4 x float> %8)
  %10 = insertvalue %struct.ColoredVertex.packed undef, <4 x float> %6, 0
  %11 = insertvalue %struct.ColoredVertex.packed %10, <4 x half> %9, 1
  ret %struct.ColoredVertex.packed %11
}

这是myFunction的定义:

1
2
3
4
define i32 @_Z10myFunctioni(i32) local_unnamed_addr #0 {
  %2 = sdiv i32 %0, 2
  ret i32 %2
}

这里要注意的重要一点是名称myFunction被弄乱了,这意味着它具有C-linkage,而名称vertex_main没有被弄乱了,这意味着它具有C-linkage。因此,我们可以推断出将函数声明为vertex会自动为其提供C链接。 (fragment_main也是未修改的。)

可能使用了C链接,因为未修改的名称更易于在运行时查找。 (回想一下,我们在运行时使用-[MTLLibrary newFunctionWithName:]按名称查找着色器函数。)

我猜想a?与Ca?不兼容?警告对您而言并不重要。我认为ColoredVertex是否与Ca不兼容?因为它具有非平凡的构造函数,但除此之外,它还是C兼容的POD(普通的数据类型)。