iOS Metal語言規范(一)

一.Metal簡述

? ??????????Metal著色器語言是用來編寫3D圖形渲染邏輯、并行Metal計算核心邏輯的一門編程語言,當你使用Metal框架來完成APP的實現時則需要使用Metal編程語言。

????????????Metal語言使用Clang 和LLVM進行編譯處理,編譯器對于在GPU上的代碼執行效率有更好的控制

????????????Metal基于C++ 11.0語言設計的,在C++基礎上多了一些擴展和限制,主要用來編寫在GPU上執行的圖像渲染邏輯代碼以及通用并行計算邏輯代碼

????????????Metal 像素坐標系統:Metal中紋理 或者 幀緩存區attachment的像素使用的坐標系統的原點是左上角

1.1Metal 語?中不?持之處?

????????Lambda 表達式;

????????遞歸函數調?

????????動態轉換操作符

????????類型識別

????????對象創建new 和銷毀delete 操作符;

????????操作符 noexcept

????????goto 跳轉

????????變量存儲修飾符register 和 thread_local;

????????虛函數修飾符;

????????派?類

????????異常處理

????????C++ 標準庫在Metal 語?中也不可使?;

1.2Metal 語?中對于指針使?的限制

????????Metal圖形和并?計算函數?到的?參數; 如果是指針必須使?地址空間修飾符(device,threadgroup,constant)

????????不?持函數指針;

????????函數名不能出現main

二.Metal的數據類型及語法

2.1? ? ?Metal 數據類型--標量數據類型?

????????bool 布爾類型, true/false

????????char 有符號8位整數;

????????unsigned char /uchar ?符號8-bit 整數;

????????short 有符號16-bit整數;

????????unsigned short / ushort ?符號32-bit 整數;

????????half 16位bit 浮點數;

????????float 32bit 浮點數;

????????size_t 64 ?符號整數;

????????void 該類型表示?個空的值集合

說明:其中half?相當于OC中的float,float?相當于OC中的doublesize_t用來表示內存空間, 相當于 OC中?sizeof

示例:boola=true;charb=5;intd=15;//用于表示內存空間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}

????????;//通過內建函數float4初始化

????????float4 pos=float4(1.0,2.0,3.0,4.0);

????????//通過下標從向量中獲取某個值

????????floatx=pos[0];floaty=pos[1];

????????//通過for循環對一個向量進行運算

????????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可以是大寫,也可以是小寫

向量的訪問規則:

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表示矩陣的行數和列數,最多4行4列,其中half、float相當于OC中的float、double- 普通的矩陣其本質就是一個數組

????????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.紋理

紋理類型

紋理類型是一個句柄,指向一維/二維/三維紋理數據,而紋理數據對應一個紋理的某個level的mipmap的全部或者一部分

紋理的訪問權限

在一個函數中描述紋理對象的類型

access枚舉值由Metal定義,定義了紋理的訪問權利enum class access {sample, read, write};,有以下3種訪問權利,當沒寫access時,默認的access 就是sample

sample: 紋理對象可以被采樣(即使用采樣器去紋理中讀取數據,相當于OpenGL ES的GLSL中sampler2D),采樣一維這時使用 或者 不使用都可以從紋理中讀取數據(即可讀可寫可采樣)

read:不使用采樣器,一個圖形渲染函數或者一個并行計算函數可以讀取紋理對象(即僅可讀)

write:一個圖形渲染函數 或者 一個并行計算可以向紋理對象寫入數據(即可讀可寫)

定義紋理類型

描述一個紋理對象/類型,有以下三種方式,分別對應一維/二維/三維,

其中T代表泛型,設定了從紋理中讀取數據 或是 寫入時的顏色類型,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>,讀取的數據類型是float,沒寫access,默認是sample

? ? - texture2d<float,access::read>,讀取的數據類型是float,讀取的方式是read

? ? - texture2d<float,access::write>,讀取的數據類型是float,讀取的方式是write

變量名

? ? - imgA

? ? - imgB

? ? - imgC

修飾符

? ? - [[texture(0)]] 對應紋理0

? ? - [[texture(1)]] 對應紋理1

? ? - [[texture(2)]] 對應紋理2

*/函數舉例

void foo (texture2d<float> imgA[[texture(0)]],

? ? ? ? ? texture2d<float,access::read> imgB[[texture(1)]],

? ? ? ? ? texture2d<float,access::write> imgC[[texture(2)]])

{

? ? //...

}

2.采樣器

????????采樣器類型決定了如何對一個紋理進行采樣操作,在Metal框架中有一個對應著色器語言的采樣器的對象MTLSamplerState,這個對象作為圖形渲染著色器函數參數或是并行計算函數的參數傳遞,有以下幾種狀態:

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 };


采樣器狀態
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。