Metal shading language简单介绍

2020-08-27  本文已影响0人  HardCabbage
一、Metal语⾔介绍
Metal 语⾔中不⽀持之处:
Metal Restrictions 限制
二、Metal 数据类型--标量数据类型 Metal数据类型
三、纹理Textures 类型

纹理类型是⼀个句柄, 它指向⼀个⼀维/⼆维/三维纹理数据。在⼀个函数中描述纹理对象的类型,定义一个枚举类型,enum class access {sample ,read ,write};

texture1d<T, access a = access::sample> 
texture2d<T, access a = access::sample>
texture3d<T, access a = access::sample>
T : 数据类型 设定了从纹理中读取或是向纹理中写⼊时的颜⾊类型. T可以是half, float, short, int 等;

///具体示例
void foo (texture2d<float> imgA [[ texture(0) ]] , 
texture2d<float, access::read> imgB [[ texture(1) ]], 
texture2d<float, access::write> imgC [[ texture(2) ]]) {  ...  }
四、采样器类型 Samplers
采样去Samplers

采取器类型决定了如何对⼀个纹理进⾏采样操作. 在Metal 框架中有⼀个对应着⾊器语⾔的采样器的对象MTLSamplerState这个对象作为图形渲染着⾊器函数参数或是并⾏计算函数的参数传递。

注意: 在Metal 程序中初始化的采样器必须使⽤ constexpr 修饰符声明 !
constexpr sampler s(coord::pixel,address::clamp_to_zero, filter::linear);
 constexpr sampler a(coord::normalized); 
 constexpr sampler b(address::repeat); 
constexpr sampler s(address::clamp_to_zero,  filter::linear,
六、函数修饰符

Metal 有以下3种函数修饰符:

kernel void foo(...)  {  ...  }

注意: ⼀个被函数修饰符修饰的函数不能在调⽤其他也被函数修饰符修饰的函数; 这样会导致编译失败;
只有图形着⾊函数才可以被 vertex 和 fragment 修饰. 对于图形着⾊函数, 返回值类型可以辨认出它是为 顶点做计算还是为每像素做计算. 图形着⾊函数的返回值可以为 void , 但是这也就意味着该函数不产⽣数 据输出到绘制管线; 这是⼀个⽆意义的动作;

七、⽤于变量或者参数的地址空间修饰符

Metal 着⾊器语⾔使⽤ 地址空间修饰符 来表示⼀个函数变量或者参数变量 被分配于那⼀⽚内存区域. 所有的着⾊函数(vertex, fragment, kernel)的参数,如果是指针或是引⽤, 都必须带有地址空间修饰符号;

// an array of a float vector with  components 
 device float4 *color; 
 struct Foo { 
 float a[3];
  int b[2]; 
 }; 
 // an array of Foo elements 
 device Foo *my_info;

注意: 纹理对象总是在设备地址空间分配内存, device 地址空间修饰符不必出现在纹理类型定义中. ⼀个纹 理对象的内容⽆法直接访问. Metal 提供读写纹理的内建函数;

kernel void my_func(threadgroup float *a [[ threadgroup(0) ]], ...)  { 
 // A float allocated in threadgroup address space 
 threadgroup float x; 
 // An array of 10 floats allocated in 
 // threadgroup address space 
threadgroup float b[10]; 
 }
constant float samples[] = { 1.0f, 2.0f, 3.0f, 4.0f }; 
 //对⼀个常量地址空间的变量进⾏修改也会失败,因为它只读的 sampler[4] = {3,3,3,3};
 //编译失败; 
 //定义为常量地址空间声明时不赋初值也会编译失败 
 constant float a; 
kernel void my_func(...) 
 { 
 float x; 
thread float p = &x; 
 ... 
 }
 kernel void add_vectors(const device float4 *inA [[ buffer(0) ]],      const device float4 *inB [[ buffer(1) ]], 
device float4 *out [[ buffer(2) ]], 
 uint id [[ thread_position_in_grid ]]) 
 { 
 out[id] = inA[id] + inB[id]; 
 }
上一篇 下一篇

猜你喜欢

热点阅读