No `simd_packed_float3` in Swift?

Hey!
I stumbled upon this issue.
There is no simd_packed_float3 type in Swift.

Why it's a problem?

Consider this Metal struct:

struct Test{
    packed_float3 x;
    float y;
};

First of all, you can't calculate a buffer pointer to address the memory of y, since you can't do this:

MemoryLayout<simd_packed_float3>.size

(Not sure if stride makes sense with packed types, but anyway with simd types it always gives the same length as size on my devices)

You can't use MemoryLayout<simd_float3>.size either, since it will return 16 and not 12 like in architectures available to me for testing.

Second, if you need to write a packed_float3 value of x to the buffer you will need to write the three consecutive floats, but not a single simd type. Again, simd_float3 is not usable since it will write 0 into the forth word corrupting the memory of the next property in the struct (y).

So I've done this:

struct Float_3{
   var x: Float
   var y: Float
   var z: Float
}

typealias simd_packed_float3 = Float_3

It seems to be a functioning solution, but I'm not sure it's not a nasty thing to do...

What problems may I encounter with this approach, and how could I be sure that it won't break on some device that I don't have?

1 Like

This is not guaranteed to work and may break in the future. Swift does not make any guarantees about the layout of stored properties in a structure.

Is MTLPackedFloat3 what you're looking for? If not, I'd recommend defining your own packed float3 type in a C header and using Swift bridging, since C does make guarantees about the layout of a structure.

2 Likes

There's no simd_packed_float3 in C or C++ either; the type cannot be defined in clang. This is why it doesn't exist in Swift.

You should use a tuple-of-three-floats in your CPU-side struct, or the MTLPackedFloat3 convenience; this is guaranteed to have the correct layout for packed_float3 on the GPU.

6 Likes

Thank you guys! This is exactly what I needed!

2 Likes