Search code examples
metal

Determine the element's type of a buffer in the Metal Shader Language


I use a codegen for generating declarations of Metal shaders and sometimes I do not know the exact types of objects that are passed to shaders.

E.g. I would have this declaration generated automatically:

vertex VertexOut vertexShader(constant Element *array [[buffer(0)]])

When I try to get the element's type of the array I get the error from the compiler:

using T = metal::remove_reference_t<decltype( *array )>;
T test;// <-- ERROR! "Automatic variable qualified with an address space"

Is this possible to "erase" the address space from the type?

What is the best way of getting the type of an array's element in Metal (if it's possible at all)?


Solution

  • As I said in the comment, I think the problem is that remove_reference does exactly what it says: it removes reference, while still leaving the type qualified. You can not declare a variable in device or constant space, so you also need to remove the address space qualifier, similar to how remove_cv_t works. I've written up a couple templates to show you what I mean:

    template <typename T>
    struct remove_address_space
    {
      typedef T type;
    };
    
    template <typename T>
    struct remove_address_space<device T>
    {
      typedef T type;
    };
    template <typename T>
    struct remove_address_space<constant T>
    {
      typedef T type;
    };
    

    and then you would use it like

    using T = remove_address_space<metal::remove_reference_t<decltype( *array )>>::type;
    

    Keep in mind that metal has a lot of address spaces, but for the purposes of writing entry points to functions, I think only the device and constant are relevant.