1.数据类型
//例如: bool a= true; char b = 5; int d = 15;
2.向量支持以下类型
booln, charn, shortn, intn, ucharn, ushortn, uintn, halfn, floatn, n指的是维度
//例如:bool2 A=[1,0]; float4 pos = float4(1.0,2.0,3.0,4.0);
** float** x = pos[0]; float y = pos[1];
** float4** vb;
** for**(int i = 0;i<4;i++){ vb[i] = pos[i] * 2.0f; }
-
支持通过向量字母来获取对应元素(xyzw和rgba) ,但不允许 rgba和xyzw 混合使用 int4 test = int4(0,1,2,3); int a = test.x; int e = test.r;
-
分量允许多个分量乱序/重复出现
** float4** dup = pos.xxyy; float4 swiz = pos.wxyz;
- 不允许超过其维度去访问变量. xy
** float2** pos;pos.x = 1.0f;//合法 pos.z = 1.0f;//不合法
- 多个向量构造器的使用
** float** x = 1.0f,y = 2.0f,z = 3.0f,w = 4.0f;
** float4** a = float4(0.0f);
** float4** b = float4(x,y,z,w);
** float2** c = float2(5.0f,6.0f);
** float2** a = float2(x,y);
** float2** b = float2(z,w);
** float4** x = float4(a.xy,b.xy);
float2 a1 = float2(1.0,1.0);
** float2** a2 = float2(2.0,2.0);
** float2x2** a = float2x2(a1,a2);
3.矩阵支持一下类型
halfnxm, floatnxm, n和m分别指的矩阵的行和列
矩阵不支持从多个标量构造 float2x2(float a00,float a01,float a02,float a00); 非法矩阵不支持标量和向量混合构造 float2x3(float2 a,float b,float c,float d);非法支持这样赋值 float4x4 m; 指的将第二排向量(x,y,z,w)赋值都为2.0f m[1] = float4(2.0f); m[0][0] = 1.0f;4.定义一块缓存, metal所谓缓存就是一个块用的指针指向区域(显存) 2个修饰符device(设备空间), constant(设备空间只读)
device float4 *device_buffer;
//结构体 struct my_user_data { float4 a; float2 c; int b; }; constant my_user_data *user_data;
5. 纹理.
//纹理数据类型就是一个句柄. 它指向一个一维/二维/三维纹理数据. 常用的就是texture2d, sample标示此纹理可以被采样
enum class access {sample,read,write};
texture1d<T,access a = access::sample>
texture1d_array<T,access a = access::sample>
texture2d<T,access a = access::sample>
texture2d_array<T,access a = access::sample>
texture3d<T,access a = access::sample>
texturecube<T,access a = access::sample>
texture2d_ms<T,access a = access::read>
//带有深度格式的纹理必须被声明为下面纹理数据类型中的一个
enum class depth_forma {depth_float};
depth2d<T,access a = depth_format::depth_float>
depth2d_array<T,access a = access::sample,depth_format d = depth_format::depth_float>
depthcube<T,access a = access::sample,depth_format d = depth_format::depth_float>
depth2d_ms<T,access a = access::read,depth_format d = depth_format::depth_float>
void foo (texture2d<float> imgA[[texture(0)]], texture2d<float,access::read> imgB[[texture(1)]], texture2d<float,access::write> imgC[[texture(2)]])
}
6.函数修饰符:
-
kernel: 并行计算函数(开发过程中, 基本上不适用)
kernel void CCTestKernelFunctionA(int a,int b) { /* 注意: 1. 使用kernel 修饰的函数返回值必须是void 类型 2. 一个被函数修饰符修饰过的函数,不允许在调用其他的被函数修饰过的函数. 非法 3. 被函数修饰符修饰过的函数,只允许在客户端对其进行操作. 不允许被普通的函数调用. *// //不可以的! //一个被函数修饰符修饰过的函数,不允许在调用其他的被函数修饰过的函数. 非法 CCTestKernelFunctionB(1,2);//非法 CCTestVertexFunctionB(1,2);//非法 //可以! 你可以调用普通函数.而且在Metal 不仅仅只有这3种被修饰过的函数.普通函数也可以存在 CCTest()}kernel void CCTestKernelFunctionB(int a,int b){}
-
vertex: 顶点函数
-
vertex int CCTestVertexFunctionB(int a,int b){ }//函数修饰符vertex 返回值类型RasterizerData 函数名字vertexShader //uint vertexID [[ vertex_id ]]是内建的, 我们无法修改, metal规定必须这样, 由它自己处理 vertex RasterizerDatavertexShader(uint vertexID [[ vertex_id ]], constant CCVertex *vertexArray [[ buffer(0) ]], constant vector_uint2 *viewportSizePointer [[buffer(1)]]){ //定点函数的输出 就是片元函数的输入}
-
fragment: 片元函数
-
fragment half4 fragmentShader(RasterizerData input [[stage_in]], texture2d textureColor [[ texture(0) ]]){
}
7.属性修饰符
-
device buffer(设备缓存)
-
constant buffer(常量缓存)
-
texture Object(纹理对象)
-
sampler Object(采样器对象)
属性修饰符目的:
-
参数表示资源如何定位? 可以理解为端口
-
在固定管线和可编程管线进行内建变量的传递
-
将数据沿着渲染管线从顶点函数传递片元函数.
在代码中如何表现:
1.已知条件:device buffer(设备缓存)/constant buffer(常量缓存) 代码表现:[[buffer(index)]] 解读:不变的buffer ,index 可以由开发者来指定.
2.已知条件:texture Object(纹理对象) 代码表现: [[texture(index)]] 解读:不变的texture ,index 可以由开发者来指定. 3.已知条件:sampler Object(采样器对象) 代码表示: [[sampler(index)]] 解读:不变的sampler ,index 可以由开发者来指定.
Metal使用大致分为:
- build :shader(vertexShader和fragmentShader)
- initialize :device and Queues Render Objects
- Render:commandBuffer、ResourceUpdate、renderEncoder、Display
初始化Device
guard let device = MTLCreateSystemDefaultDevice() else {
fatalError("Could not create Metal Device")
}
创建 CommandQueue 命令队列
guard let commandQueue = self.device.makeCommandQueue() else {
fatalError("Could not create command queue")
}
创建 Buffer 数据:
与 OpenGL 类似的,顶点、索引等数据都通过 Buffer 管理。 比如:vertexBuffer、textureCoordBuffer
/// 纹理坐标buffer
let coordinateBuffer = device.makeBuffer(bytes: inputTextureCoordinates,
length: inputTextureCoordinates.count * MemoryLayout<Float>.size,
options: [])!
///顶点数据buffer
let vertexBuffer = device.makeBuffer(bytes: imageVertices,
length: imageVertices.count * MemoryLayout<Float>.size,
options: [])!