Search code examples
c++objective-cstructpaddingmetal

Coordinating the padding of structs in C++ and Objective-C


I’m using Objective-C and Metal to render to a window, however all of my application code is written in C++. So all of the CPU manipulation of data inside MTLBuffer is done in C++. This is done by passing the buffers contents (which is a void*) to the C++ code, where it casts the contents pointer to MyVertex* to write new vertex data. In my header file, i just add compiler conditions to type the vertex structs properly.

#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;

Here vec2, vec4 are basically structs of 2, 4 floats implemented in my C++ code. But in this example, Objective-C and C++ think that MyVertex is of differing sizes. I’m compiling with clang and clang++. And the Objective-C compiler wants to pad the struct so it is of size 32, while C++ says that the struct is of size 24. I currently fixed this now with #pragma pack, but this feels like a weak solution. I would actually prefer my C++ implementation to be padded instead of packed to better optimize buffers in the shaders. But I cannot deliberately pad a struct like I can pack one.

Should I make my own vectors (vec2…) compatible with Objective-C? Right now they are written as classes. That way i won’t have to do conditional declarations. I would prefer the solution to best optimize buffer performance in the shader.


Solution

  • Since Objective-C expects every field of your struct to align at a 16-byte (4 floats) boundary, you can ask C++ to do the same with alignas(16)

    struct MyVertex {
        alignas(16) V2 position;
        alignas(16) V4 color;
    };
    

    This will adjust the offsets and resulting size of MyVertex:

    offsetof(MyVertex, position):0
    offsetof(MyVertex, color):16
    sizeof(MyVertex): 32