When working with Metal, I find there's a bewildering number of types and it's not always clear to me which type I should be using in which context.
In Apple's Metal Shading Language Specification, there's a pretty clear table of which types are supported within a Metal shader file. However, there's plenty of sample code available that seems to use additional types that are part of SIMD. On the macOS (Objective-C) side of things, the Metal types are not available but the SIMD ones are and I'm not sure which ones I'm supposed to be used.
For example:
In the Metal Spec, there's float2
that is described as a "vector" data type representing two floating components.
On the app side, the following all seem to be used or represented in some capacity:
float2
, which is typedef ::simd_float2 float2
in vector_types.h
Noted: "In C or Objective-C, this type is available as simd_float2."
vector_float2
, which is typedef simd_float2 vector_float2
Noted: "This type is deprecated; you should use simd_float2 or simd::float2 instead"
simd_float2
, which is typedef __attribute__((__ext_vector_type__(2))) float simd_float2
::simd_float2
and simd::float2
?A similar situation exists for matrix types:
matrix_float4x4
, simd_float4x4
, ::simd_float4x4
and float4x4
, Could someone please shed some light on why there are so many typedefs with seemingly overlapping functionality? If you were writing a new application today (2018) in Objective-C / Objective-C++, which type should you use to represent two floating values (x/y) and which type for matrix transforms that can be shared between app code and Metal?
The types with vector_
and matrix_
prefixes have been deprecated in favor of those with the simd_
prefix, so the general guidance (using float4
as an example) would be:
simd_float4
type. (You have to include the prefix unless you provide your own typedef
, since C doesn't have namespaces.)simd::float4
type, which you can shorten to float4
by using namespace simd;
.float4
type, since float4
is a fundamental type in the Metal Shading Language [1].float4
type, since the simd_
types are typealiased to shorter names.float4
and related types have been deprecated in favor of SIMD4<Float>
and related types.These types are all fundamentally equivalent, and all have the same size and alignment characteristics so you can use them across languages. That is, in fact, one of the design goals of the simd framework.
I'll leave a discussion of packed types to another day, since you didn't ask.
[1] Metal is an unusual case since it defines float4
in the global namespace, then imports it into the metal
namespace, which is also exported as the simd
namespace. It additionally aliases float4
as vector_float4
. So, you can use any of the above names for this vector type (except simd_float4
). Prefer float4
.