Metal着色器语言中获取缓冲区元素类型及移除地址空间限定方法
Metal着色器中获取数组元素类型并擦除地址空间的方法
问题根源
Metal的地址空间限定符(constant、device、threadgroup等)是类型的一部分,当你对constant Element*类型的指针解引用时,decltype(*array)得到的是constant Element——直接声明这种带地址空间限定的自动变量会触发编译器错误,因为自动变量不允许带有地址空间修饰。
解决方案
1. 自定义类型萃取器擦除地址空间
你可以编写一个模板元工具,专门移除类型中的地址空间限定:
#include <metal_stdlib> template <typename T> struct remove_address_space { using type = T; }; // 针对各种地址空间特化 template <typename T> struct remove_address_space<const T> { using type = typename remove_address_space<T>::type; }; template <typename T> struct remove_address_space<device T> { using type = typename remove_address_space<T>::type; }; template <typename T> struct remove_address_space<constant T> { using type = typename remove_address_space<T>::type; }; template <typename T> struct remove_address_space<threadgroup T> { using type = typename remove_address_space<T>::type; }; // 简化类型别名 template <typename T> using remove_address_space_t = typename remove_address_space<T>::type;
之后就可以安全地获取并使用元素类型:
vertex VertexOut vertexShader(constant Element *array [[buffer(0)]]) { // 先解引用拿到带地址空间的类型,再移除地址空间 using T = remove_address_space_t<metal::remove_reference_t<decltype(*array)>>; T test; // 不再报错 // ... 后续逻辑 }
2. 直接从指针类型萃取元素类型(更高效)
既然输入是指针类型,你可以跳过解引用步骤,直接从指针类型中提取指向的元素类型,再移除地址空间:
vertex VertexOut vertexShader(constant Element *array [[buffer(0)]]) { // 先移除指针修饰,再移除地址空间 using T = remove_address_space_t<metal::remove_pointer_t<decltype(array)>>; T test; // 同样可行 // ... 后续逻辑 }
最佳实践
优先使用第二种方法:直接从指针类型出发萃取元素类型,避免解引用带来的地址空间限定问题,代码更简洁高效。如果需要处理非指针的带地址空间类型(比如constant Element变量),再使用第一种自定义萃取器的方案。
内容的提问来源于stack exchange,提问作者Roman Gaditskii
相关产品推荐
相关产品推荐

