Reputation: 65543
I need to pass a struct with a packed_float3
(MTLPackedFloat3
) value from Swift into my Metal shader. I am currently sharing types between Swift and metal using a bridging header. Here's the struct I am trying to write:
typedef struct {
packed_float3 value;
} CustomData;
However when I try using packed_float3
, I get the following error:
unknown type name 'packed_float3'
I've tried all sort of type variations including MTLPackedFloat3
, packed_simd_float3
, metal::packed_float3
, vector_packed_float3
, packed<float, 3>
but none of them work. I've also tried including various other headers such as <metal/metal.h>
or <metal/MTLAccelerationStructureTypes.h>
but this often produces other compiler errors
How can I use packed values in bridging headers without having to define my own types?
Upvotes: 0
Views: 159
Reputation: 65543
There's likely a better way to do this but here's what worked for me:
I believe the root cause is that the bridging header is essentially "built" twice in two different environments: once for Swift and once for Metal. packed_float3
for example is always defined in Metal but isn't defined in Swift. On the other hand, MTLPackedFloat3
works fine in Swift isn't defined in Metal.
As a workaround, we can use preprocessing to vary the types used in the Metal compile vs in the swift compile. A simple way to do this is to check if __METAL_VERSION__
is defined as it will only be defined when the header is included in Metal. Now for Swift, we can alias packed_float3
to the Swift type MTLPackedFloat3
:
#ifndef __METAL_VERSION__
#include <metal/metal.h>
typedef MTLPackedFloat3 packed_float3;
#endif
This code will only be active in the Swift compile. It also counts on MTLPackedFloat3
and packed_float3
having the same data layout. Now you can use packed_float3
in the header for both Swift and Metal!
Interested to hear if there's a better approach because this is pretty ugly
Upvotes: 0