我使用 Objective-C 和 Metal 渲染到窗口,但是我的所有应用程序代码都是用 C++ 编写的。因此,
MTLBuffer
内的所有 CPU 数据操作都是用 C++ 完成的。这是通过将缓冲区内容(即 void*
)传递给 C++ 代码来完成的,其中它将内容指针转换为 MyVertex*
以写入新的顶点数据。在我的头文件中,我只是添加编译器条件以正确键入顶点结构。
#ifdef __IN_OBJC__
#define V2 vector_float2
#define V4 vector_float4
#endif
#ifdef __IN_CPP__
#define V2 vec2
#define V4 vec4
#endif
typedef struct {
V2 position;
V4 color;
} MyVertex;
这里
vec2
、vec4
基本上是在我的 C++ 代码中实现的 2、4 个浮点数的结构。但在这个例子中,Objective-C 和 C++ 认为 MyVertex
的大小不同。我正在使用 clang 和 clang++ 进行编译。 Objective-C 编译器想要填充结构体,使其大小为 32,而 C++ 则表示结构体大小为 24。我目前使用 #pragma pack
修复了此问题,但这感觉像是一个较弱的解决方案。实际上,我更希望对我的 C++ 实现进行填充而不是打包,以更好地优化着色器中的缓冲区。但我不能像打包结构那样故意填充结构。
我应该让自己的向量(
vec2
…)与 Objective-C 兼容吗?现在它们被写成类。这样我就不必做条件声明。我更喜欢能够最好地优化着色器中的缓冲区性能的解决方案。
由于 Objective-C 希望结构体的每个字段都在 16 字节(4 个浮点)边界对齐,因此您可以要求 C++ 执行相同操作
alignas(16)
struct MyVertex {
alignas(16) V2 position;
alignas(16) V4 color;
};
这将调整
MyVertex
的偏移量和最终大小:
offsetof(MyVertex, position):0
offsetof(MyVertex, color):16
sizeof(MyVertex): 32