Search code examples
cpointersmetaluint8t

How do I cast a float pointer to a uint8_t pointer in Metal Shader Language?


I am trying to write the following C code in Metal Shading Language inside of a kernel void function:

float f = 2.1;
uint8_t byteArray[sizeof(f)];
for (int a = 0; a < sizeof(f); a++) {
    byteArray[a] = ((uint8_t*)&f)[a];
}

The code is supposed to get a byte array of the float value. When I try to write the same code in Metal Shader Language, I get the following build-time error:

Pointer type must have explicit address space qualifier

I understand that Metal restricts the use of pointers and requires that arguments to a kernel function are provided with an explicit address space attribute such as device, constant, etc. How would I perform the type-cast in Metal Shading Language?


Solution

  • This isn't C++, so you have to do it the other way.

    You can't use unions or reinterpret_cast in MSL properly.

    Instead, there's a type for a vector of 4 uint8_ts, it's uchar4.

    To do what you are trying to do, you would write it something like this.

    float f = 2.1;
    uchar4 ff = as_type<uchar4>(f);
    

    Refer to the MSL spec, section 2.19 Type Conversions and Re-interpreting data.

    As for address space qualifiers:

    Every pointer in Metal Shading Language has an address qualifier. It can be a device, constant, thread, threadgroup and others. Refer to Chapter 4 in the spec.

    These address qualifiers come from the fact that there are different memory spaces. You can read more about them in the document above.

    Since f is local variable, it's in thread space, so your uint8_t pointer would have a type of thread uint8_t* and not just uint8_t.

    So you could probably do it like this:

    float f = 2.1;
    thread uint8_t* ff = (thread uint8_t*)&f;
    

    But I think the as_type approach is much more clear.