一.Metal簡述
? ??????????Metal著色器語言是用來編寫3D圖形渲染邏輯恐锦、并行Metal計算核心邏輯的一門編程語言一铅,當你使用Metal框架來完成APP的實現(xiàn)時則需要使用Metal編程語言。
????????????Metal語言使用Clang 和LLVM進行編譯處理肮之,編譯器對于在GPU上的代碼執(zhí)行效率有更好的控制
????????????Metal基于C++ 11.0語言設計的戈擒,在C++基礎上多了一些擴展和限制,主要用來編寫在GPU上執(zhí)行的圖像渲染邏輯代碼以及通用并行計算邏輯代碼
????????????Metal 像素坐標系統(tǒng):Metal中紋理 或者 幀緩存區(qū)attachment的像素使用的坐標系統(tǒng)的原點是左上角
1.1Metal 語?中不?持之處?
????????Lambda 表達式;
????????遞歸函數(shù)調(diào)?
????????動態(tài)轉換操作符
????????類型識別
????????對象創(chuàng)建new 和銷毀delete 操作符;
????????操作符 noexcept
????????goto 跳轉
????????變量存儲修飾符register 和 thread_local;
????????虛函數(shù)修飾符;
????????派?類
????????異常處理
????????C++ 標準庫在Metal 語?中也不可使?;
1.2Metal 語?中對于指針使?的限制
????????Metal圖形和并?計算函數(shù)?到的?參數(shù); 如果是指針必須使?地址空間修飾符(device,threadgroup,constant)
????????不?持函數(shù)指針;
????????函數(shù)名不能出現(xiàn)main
二.Metal的數(shù)據(jù)類型及語法
2.1? ? ?Metal 數(shù)據(jù)類型--標量數(shù)據(jù)類型?
????????bool 布爾類型, true/false
????????char 有符號8位整數(shù);
????????unsigned char /uchar ?符號8-bit 整數(shù);
????????short 有符號16-bit整數(shù);
????????unsigned short / ushort ?符號32-bit 整數(shù);
????????half 16位bit 浮點數(shù);
????????float 32bit 浮點數(shù);
????????size_t 64 ?符號整數(shù);
????????void 該類型表示?個空的值集合
說明:其中half?相當于OC中的float艰毒,float?相當于OC中的doublesize_t用來表示內(nèi)存空間筐高, 相當于 OC中?sizeof
示例:boola=true;charb=5;intd=15;//用于表示內(nèi)存空間size_t c=1;ptrdiff_t f=2;
2.2Metal向量
????????向量支持如下類型:- booln、charn丑瞧、shortn柑土、intn、ucharn嗦篱、ushortn冰单、uintn、halfn灸促、floatn,其中 n 表示向量的維度浴栽,最多不超過4維向量示例:
????????//直接賦值初始化
????????bool2 A={1,2}
????????;//通過內(nèi)建函數(shù)float4初始化
????????float4 pos=float4(1.0,2.0,3.0,4.0);
????????//通過下標從向量中獲取某個值
????????floatx=pos[0];floaty=pos[1];
????????//通過for循環(huán)對一個向量進行運算
????????float4 VB;
????????for(inti=0;i<4;i++){
????????????VB[i]=pos[i]*2.0f;
????????}
? ??????說明:在OpenGL ES的GLSL語言中荒叼,例如2.0f,在著色器中書寫時典鸡,是不能加f被廓,寫成2.0,而在Metal中則可以寫成2.0f萝玷,其中f可以是大寫,也可以是小寫
向量的訪問規(guī)則:
1.通過向量字母獲取元素: 向量中的向量字母僅有2種,分別為xyzw咒精、rgba
? ??????int4 test=int4(0,1,2,3);
????????inta=test.x; //獲取的向量元素0
????????intb=test.y; //獲取的向量元素1
????????intc=test.z; //獲取的向量元素2
????????intd=test.w;//獲取的向量元素3
????????inte=test.r; //獲取的向量元素0
????????intf=test.g魂那;//獲取的向量元素1
????????intg=test.b; //獲取的向量元素2
????????inth=test.a; //獲取的向量元素3
2.多個分量同時訪問
????????float4 c;
????????c.xyzw=float4(1.0f,2.0f,3.0f,4.0f);
????????c.z=1.0f
????????c.xy=float2(3.0f,4.0f);
????????c.xyz=float3(3.0f,4.0f,5.0f);
? ??????說明:賦值時分量不可重復,取值時分量可重復右邊是取值?和?左邊賦值都合法xyzw與rgba不能混合使用,GLSL中向量不能亂序訪問,只是和Metal中的向量相似,并不是等價看疙。
2.3矩陣
????????矩陣支持如下類型-?halfnxm、floatnxm直奋,其中?nxm表示矩陣的行數(shù)和列數(shù)能庆,最多4行4列,其中half脚线、float相當于OC中的float搁胆、double- 普通的矩陣其本質(zhì)就是一個數(shù)組
????????float4x4 m;
????????//將第二行的所有值都設置為2.0
????????m[1]=float4(2.0f);
????????//設置第一行/第一列為1.0f
????????m[0][0]=1.0f;
????????//設置第三行第四列的元素為3.0f
????????m[2][3]=3.0f;
????????float4 類型向量的構造方式
????????1個float構成,表示一行都是這個值
????????4個float構成
????????2個float2構成
????????1個float2+2個float構成(順序可以任意組合)
????????1個float2+1個float
????????1個float4
eg:
????????//float4類型向量的所有可能構造方式//1個一維向量,表示一行都是xfloat4(floatx);
? ??????///4個一維向量 --> 4維向量float4(floatx,floaty,floatz,floatw);
? ??????//2個二維向量 --> 4維向量float4(float2 a,float2 b);
? ??????//1個二維向量+2個一維向量 --> 4維向量float4(float2 a,float b,float c);
? ??????float4(floata,float2 b,floatc);float4(floata,floatb,float2 c);
? ??????//1個三維向量+1個一維向量 --> 4維向量float4(float3 a,floatb);float4(floata,float3 b);
//1個四維向量 --> 4維向量float4(float4 x);
float3 類型向量的構造方式
????????1個float構成,表示一行都是這個值
????????3個float
????????1個float+1個float2(順序可以任意組合)
????????1個float2
eg:
????????//float3類型向量的所有可能的構造的方式
? ??????//1個一維向量float3(floatx);
? ??????//3個一維向量float3(floatx,floaty,floatz);
? ??????//1個一維向量 + 1個二維向量float3(floata,float2 b);
? ??????/1個二維向量 + 1個一維向量float3(float2 a,floatb);
? ??????//1個三維向量float3(float3 x);
? ??????float2 類型向量的構造方式
?1個float構成,表示一行都是這個值
????????2個float
????????1個float2
eg:
????????//float2類型向量的所有可能的構造方式
? ??????//1個一維向量float2(floatx);
? ??????//2個一維向量float2(floatx,floaty)邮绿;
? ??????//1個二維向量float2(float2 x);
三丰涉,Metal的其他類型
1.紋理
紋理類型
紋理類型是一個句柄,指向一維/二維/三維紋理數(shù)據(jù)斯碌,而紋理數(shù)據(jù)對應一個紋理的某個level的mipmap的全部或者一部分
紋理的訪問權限
在一個函數(shù)中描述紋理對象的類型
access枚舉值由Metal定義一死,定義了紋理的訪問權利enum class access {sample, read, write};,有以下3種訪問權利傻唾,當沒寫access時投慈,默認的access 就是sample
sample: 紋理對象可以被采樣(即使用采樣器去紋理中讀取數(shù)據(jù),相當于OpenGL ES的GLSL中sampler2D)冠骄,采樣一維這時使用 或者 不使用都可以從紋理中讀取數(shù)據(jù)(即可讀可寫可采樣)
read:不使用采樣器伪煤,一個圖形渲染函數(shù)或者一個并行計算函數(shù)可以讀取紋理對象(即僅可讀)
write:一個圖形渲染函數(shù) 或者 一個并行計算可以向紋理對象寫入數(shù)據(jù)(即可讀可寫)
定義紋理類型
描述一個紋理對象/類型,有以下三種方式凛辣,分別對應一維/二維/三維抱既,
其中T代表泛型,設定了從紋理中讀取數(shù)據(jù) 或是 寫入時的顏色類型扁誓,T可以是half防泵、float、short蝗敢、int等
access表示紋理訪問權限捷泞,當access沒寫時,默認是sample
texture1d<T, access a = access::sample>
texture2d<T, access a = access::sample>
texture3d<T, access a = access::sample>
eg:
//類型 變量 修飾符
/*
類型
? ? - texture2d<float>寿谴,讀取的數(shù)據(jù)類型是float锁右,沒寫access,默認是sample
? ? - texture2d<float,access::read>,讀取的數(shù)據(jù)類型是float咏瑟,讀取的方式是read
? ? - texture2d<float,access::write>拂到,讀取的數(shù)據(jù)類型是float,讀取的方式是write
變量名
? ? - imgA
? ? - imgB
? ? - imgC
修飾符
? ? - [[texture(0)]] 對應紋理0
? ? - [[texture(1)]] 對應紋理1
? ? - [[texture(2)]] 對應紋理2
*/函數(shù)舉例
void foo (texture2d<float> imgA[[texture(0)]],
? ? ? ? ? texture2d<float,access::read> imgB[[texture(1)]],
? ? ? ? ? texture2d<float,access::write> imgC[[texture(2)]])
{
? ? //...
}
2.采樣器
????????采樣器類型決定了如何對一個紋理進行采樣操作码泞,在Metal框架中有一個對應著色器語言的采樣器的對象MTLSamplerState谆焊,這個對象作為圖形渲染著色器函數(shù)參數(shù)或是并行計算函數(shù)的參數(shù)傳遞,有以下幾種狀態(tài):
coord:從紋理中采樣時浦夷,紋理坐標是否需要歸一化
enum class coord { normalized, pixel };
filter:紋理采樣過濾方式,放大/縮小過濾方式
enum class filter { nearest, linear };
min_filter:設置紋理采樣的縮小過濾方式
enum class min_filter { nearest, linear };
mag_filter:設置紋理采樣的放大過濾方式
enum class mag_filter { nearest, linear };
s_address辜王、t_address劈狐、r_address:設置紋理s、t呐馆、r坐標(對應紋理坐標的x肥缔、y、z)的尋址方式
s坐標:enum class s_address { clamp_to_zero, clamp_to_edge, repeat, mirrored_repeat };
t坐標:enum class t_address { clamp_to_zero, clamp_to_edge, repeat, mirrored_repeat };
r坐標:enum class r_address { clamp_to_zero, clamp_to_edge, repeat, mirrored_repeat };
address:設置所有紋理坐標的尋址方式
enum class address { clamp_to_zero, clamp_to_edge, repeat, mirrored_repeat };
mip_filter:設置紋理采樣的mipMap過濾模式, 如果是none,那么只有一層紋理生效;
enum class mip_filter { none, nearest, linear };