Metal語法規(guī)范(備忘)

簡介

  • Metal著色器語言是用來編寫 3D圖形渲染邏輯并行Metal計算核心邏輯的一門編程語言墨闲,當(dāng)你使用Metal框架來完成APP的實現(xiàn)時則需要使用Metal編程語言氏涩。
  • Metal語言使用Clang 和LLVM進行編譯處理酬诀,編譯器對于在GPU上的代碼執(zhí)行效率有更好的控制
  • Metal基于C++ 11.0語言設(shè)計的曹质,在C++基礎(chǔ)上多了一些擴展和限制婴噩,主要用來編寫在GPU上執(zhí)行的圖像渲染邏輯代碼以及通用并行計算邏輯代碼
  • Metal 像素坐標(biāo)系統(tǒng):Metal紋理 或者 幀緩存區(qū)attachment的像素使用的坐標(biāo)系統(tǒng)的原點是左上角

限制

  • Metal中不支持C++11.0的特性:
    • Lambda表達式;
    • 遞歸函數(shù)調(diào)用
    • 動態(tài)轉(zhuǎn)換操作符
    • 類型識別
    • 對象創(chuàng)建new和銷毀delete操作符
    • 操作符noexcept
    • goto跳轉(zhuǎn)
    • 變量存儲修飾符register 和thread_local
    • 虛函數(shù)修飾符
    • 派生類
    • 異常處理
    • C++標(biāo)準(zhǔn)庫在Metal語言中也不可使用
  • Metal語言對于指針使用的限制
    • Metal圖形和并行計算函數(shù)用到的入?yún)⑷绻侵羔?code>使用地址空間修飾符 (device ,threadgroup ,constant) 不?持函數(shù)指針;
    • 函數(shù)名不能出現(xiàn)main

數(shù)據(jù)類型

基本數(shù)據(jù)類型主要有:標(biāo)量、向量羽德、矩陣

標(biāo)量

類型 描述
bool 布爾類型几莽,取值true,false宅静;true可以拓展為整數(shù)常量1章蚣,false可以拓展為整數(shù)常量0
char 有符號8-bit整數(shù)
unsigned char uchar 無符號8-bit整數(shù)
short 有符號16-bit整數(shù)
unsigned short ushort 無符號16-bit整數(shù)
int 有符號32-bit整數(shù)
unsigned int uint 無符號32-bit整數(shù)
half 一個16-bit浮點數(shù)
float 一個32-bit浮點數(shù)
size-t 64-bit無符號整數(shù),表示sizeof操作符的結(jié)果
ptrdiff_t 64-bit有符號整數(shù)坏为,表示2個指針的差
void 表示一個空的值集合

常用: bool究驴、int、uint 匀伏、half
unsigned char可以簡寫為uchar
unsigned short 可以簡寫為ushort
unsigned int 可以簡寫為 uint
half 相當(dāng)于OC中的float灿意,float相當(dāng)于OC中的double
size_t用來表示內(nèi)存空間译暂, 相當(dāng)于OC中 sizeof

bool a = true;
char b = 5;
int  d = 15;
//表示內(nèi)存空間
size_t c = 1;
ptrdiff_t f = 2;

向量

支持類型: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);

//通過下標(biāo)從向量中獲取某個值
float x = pos[0];
float y = pos[1];

//通過for循環(huán)對一個向量進行運算
float4 VB;
for(int i = 0; i < 4 ; I++)
{
    VB[i] = pos[i] * 2.0f;
}

向量的訪問規(guī)則

  • 通過向量字母獲取元素: 向量中的向量字母僅有2種矛辕,分別為xyzw笑跛、rgba
int4 test = int4(0,1,2,3);
int a = test.x; //獲取的向量元素0
int b = test.y; //獲取的向量元素1
int c = test.z; //獲取的向量元素2
int d = test.w; //獲取的向量元素3

int e = test.r; //獲取的向量元素0
int f = test.g; //獲取的向量元素1
int g = test.b; //獲取的向量元素2
int h = test.a; //獲取的向量元素3

  • 多個分量同時訪問
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);

  • 多分量訪問可以亂序/重復(fù)
    • 賦值分量不可重復(fù)取值分量可重復(fù)
    • 右邊是取值和左邊賦值都合法
    • xyzwrgba不能混合使用

注意:GLSL中向量不能亂序訪問聊品,只是和Metal中的向量相似飞蹂,并不是等價。

float4 pos = float4(1.0f,2.0f,3.0f,4.0f);
//向量分量逆序訪問
float4 swiz = pos.wxyz;  //swiz = (4.0,1.0,2.0,3.0);
//向量分量重復(fù)訪問
float4 dup = pos.xxyy;  //dup = (1.0f,1.0f,2.0f,2.0f);

//可以僅對 xw / wx 修改
//pos = (5.0f,2.0,3.0,6.0)
pos.xw = float2(5.0f,6.0f);

//pos = (8.0f,2.0f,3.0f,7.0f)
pos.wx = float2(7.0f,8.0f);

//可以僅對 xyz 進行修改
//pos = (3.0f,5.0f,9.0f,7.0f);
pos.xyz = float3(3.0f,5.0f,9.0f);

float2 pos;
pos.x = 1.0f; //合法
pos.z = 1.0f; //非法翻屈,pos是二維向量陈哑,沒有z這個索引

float3 pos2;
pos2.z = 1.0f; //合法
pos2.w = 1.0f; //非法

// 賦值 時 分量不可重復(fù),取值 時 分量可重復(fù)
//非法,x出現(xiàn)2次
pos.xx = float2(3.0,4.0f);
pos.xy = swiz.xx;

//向量中xyzw與rgba兩組分量不能混合使用
float4 pos4 = float4(1.0f,2.0f,3.0f,4.0f);
pos4.x = 1.0f;
pos4.y = 2.0f;
//非法,.rgba與.xyzw 混合使用
pos4.xg = float2(2.0f,3.0f);
////非法,.rgba與.xyzw 混合使用
float3 coord = pos4.ryz;

矩陣

矩陣支持類型:halfnxm伸眶、floatnxm惊窖,其中 nxm表示矩陣的行數(shù)和列數(shù),最多4行4列厘贼。
普通的矩陣其本質(zhì)就是一個數(shù)組爬坑。

float4x4 m;
//將第二行的所有值都設(shè)置為2.0
m[1] = float4(2.0f);

//設(shè)置第一行/第一列為1.0f
m[0][0] = 1.0f;

//設(shè)置第三行第四列的元素為3.0f
m[2][3] = 3.0f;

float4 類型向量的構(gòu)造方式

  • 1個float構(gòu)成,表示一行都是這個值
//1個一維向量,表示一行都是x
float4(float x);/

  • 4個float構(gòu)成
//4個一維向量 --> 4維向量
float4(float x,float y,float z,float w);

  • 2個float2構(gòu)成
//2個二維向量 --> 4維向量
float4(float2 a,float2 b);

  • 1個float2 + 2個float構(gòu)成(順序可以任意組合)
//1個二維向量+2個一維向量 --> 4維向量
float4(float2 a,float b,float c);
float4(float a,float2 b,float c);
float4(float a,float b,float2 c);

  • 1個float2 + 1個float
//1個三維向量+1個一維向量 --> 4維向量
float4(float3 a,float b);
float4(float a,float3 b);

  • 1個float4
//1個四維向量 --> 4維向量
float4(float4 x);

float3類型向量的構(gòu)造方式

  • 1個float構(gòu)成,表示一行都是這個值
  • 3個float
  • 1個float + 1個float2(順序可以任意組合)
  • 1個float2
//float3類型向量的所有可能的構(gòu)造的方式
//1個一維向量
float3(float x);
//3個一維向量
float3(float x,float y,float z);
//1個一維向量 + 1個二維向量
float3(float a,float2 b);
//1個二維向量 + 1個一維向量
float3(float2 a,float b);
//1個三維向量
float3(float3 x);

float2類型向量的構(gòu)造方式

  • 1個float構(gòu)成,表示一行都是這個值
  • 2個float
  • 1個float2
//float2類型向量的所有可能的構(gòu)造方式
//1個一維向量
float2(float x);
//2個一維向量
float2(float x,float y);
//1個二維向量
float2(float2 x);

紋理Textures

紋理類型是一個句柄涂臣,指向一維/二維/三維紋理數(shù)據(jù)盾计,在一個函數(shù)中描述紋理對象的類型。
而紋理數(shù)據(jù)對應(yīng)一個紋理的某個level的mipmap的全部或者一部分赁遗。
紋理的訪問權(quán)限
access枚舉值由Metal定義署辉,定義了紋理的訪問權(quán)利 enum class access {sample, read, write};,有以下3種訪問權(quán)利

  • sample: 紋理對象可以被采樣. 采樣?維這是使?或不使?采樣器從紋理中讀取數(shù)據(jù);
  • read: 不使?采樣器, ?個圖形渲染函數(shù)或者?個并?計算函數(shù)可以讀取紋理對象;
  • write: ?個圖形渲染函數(shù)或者?個并?計算函數(shù)可以向紋理對象寫?數(shù)據(jù);

當(dāng)沒寫access時岩四,默認的access 就是 sample

定義紋理類型
描述一個紋理對象/類型哭尝,有以下三種方式,分別對應(yīng)一維/二維/三維剖煌,

texture1d<T, access a = access::sample>
texture2d<T, access a = access::sample>
texture3d<T, access a = access::sample>

  • T代表泛型材鹦,設(shè)定了從紋理中讀取數(shù)據(jù) 或是 寫入時的顏色類型,如half耕姊、float桶唐、short、int
  • access表示紋理訪問權(quán)限茉兰,當(dāng)access沒寫時尤泽,默認是sample
//類型 變量 修飾符
/*
類型
 *  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)]] 對應(yīng)紋理0
 *  [[texture(1)]] 對應(yīng)紋理1
 *  [[texture(2)]] 對應(yīng)紋理2
 */
void foo (texture2d<float> imgA[[texture(0)]],
          texture2d<float,access::read> imgB[[texture(1)]],
          texture2d<float,access::write> imgC[[texture(2)]])
{

}

采樣器Samplers

采取器類型決定了如何對?個紋理進?采樣操作. 在Metal 框架中有?個對應(yīng)著?器語?的采樣器的對象MTLSamplerState這個對象作為圖形渲染著?器函數(shù)參數(shù)或是并?計算函數(shù)的參數(shù)傳遞被因。

Metal支持的采樣器和默認值

image
  • coord:從紋理中采樣時卿拴,紋理坐標(biāo)是否需要歸一化
enum class coord { normalized, pixel };

  • filter:紋理采樣過濾方式衫仑,放大/縮小過濾方式
enum class filter { nearest, linear };

  • min_filter:設(shè)置紋理采樣的縮小過濾方式
enum class min_filter { nearest, linear };

  • mag_filter:設(shè)置紋理采樣的放大過濾方式
enum class mag_filter { nearest, linear };

  • mip_filter:設(shè)置紋理采樣的mipMap過濾模式, 如果為none只有一層紋理生效
enum class mip_filter { none, nearest, linear };

  • s_address、t_address巍棱、r_address:設(shè)置紋理s惑畴、t、r坐標(biāo)(對應(yīng)紋理坐標(biāo)的x航徙、y如贷、z)的尋址方式
//s坐標(biāo)
enum class s_address { clamp_to_zero, clamp_to_edge, repeat, mirrored_repeat };
//t坐標(biāo)
enum class t_address { clamp_to_zero, clamp_to_edge, repeat, mirrored_repeat };
//r坐標(biāo)
enum class r_address { clamp_to_zero, clamp_to_edge, repeat, mirrored_repeat };

  • address:設(shè)置所有紋理坐標(biāo)的尋址方式
enum class address { clamp_to_zero, clamp_to_edge, repeat, mirrored_repeat };

注意:在Metal 程序中初始化的采樣器必須使? constexpr修飾符聲明

/*
 * constexpr:修飾符(必須寫)
 * sampler:類型
 * s:采樣器變量名稱
參數(shù)
 * coord: 是否需要歸一化,不需要歸一化到踏,用的是像素pixel
 * address: 地址環(huán)繞方式
 * filter: 過濾方式
*/
constexpr sampler s(coord::pixel, address::clamp_to_zero, filter::linear);
constexpr sampler a(coord::normalized);
constexpr sampler b(address::repeat);

函數(shù)修飾符

Metal有以下3種函數(shù)修飾符:

  • kernel, 表示該函數(shù)是?個數(shù)據(jù)并?計算著?函數(shù). 它可以被分配在?維/?維/三維線程組中去執(zhí)?
  • vertex , 表示該函數(shù)是?個頂點著?函數(shù) , 它將為頂點數(shù)據(jù)流中的每個頂點數(shù)據(jù)執(zhí)??次然后為每個頂點?成數(shù)據(jù)輸出到繪制管線
  • fragment,表示該函數(shù)是?個?元著?函數(shù), 它將為?元數(shù)據(jù)流中的每個?元和其關(guān)聯(lián)執(zhí)??次然后將每個?元?成的顏?數(shù)據(jù)輸出到繪制管線中

注意

  • 使用kernel修飾的函數(shù)杠袱,其返回值類型必須void類型
  • ?個被函數(shù)修飾符修飾的函數(shù)不能在調(diào)?其他也被函數(shù)修飾符修飾的函數(shù),這樣會導(dǎo)致編譯失敗窝稿。
  • 被函數(shù)修飾符修飾過的函數(shù),只允許客戶端對其進行操作. 不允許普通的函數(shù)調(diào)用
  • 不是所有的函數(shù)都需函數(shù)修飾符修飾楣富,可以定義不帶任何修飾符的普通函數(shù)。
//并行計算函數(shù)(kernel)
kernel void CCTestKernelFunctionA(int a,int b)
{ 
    /*
     * 注意:
     * 1\. 使用kernel 修飾的函數(shù)返回值必須是void 類型
     * 2\. 一個被函數(shù)修飾符修飾過的函數(shù),不允許在調(diào)用其他的被函數(shù)修飾過的函數(shù). 非法
     * 3\. 被函數(shù)修飾符修飾過的函數(shù),只允許在客戶端對其進行操作. 不允許被普通的函數(shù)調(diào)用.
     */

    //不可以的!
    //一個被函數(shù)修飾符修飾過的函數(shù),不允許在調(diào)用其他的被函數(shù)修飾過的函數(shù). 非法
    CCTestKernelFunctionB(1,2);//非法伴榔,錯誤調(diào)用N坪!踪少!
    CCTestVertexFunctionB(1,2);//非法塘安,錯誤調(diào)用!T荨兼犯!

    //可以! 你可以調(diào)用普通函數(shù).而且在Metal 不僅僅只有這3種被修飾過的函數(shù).普通函數(shù)也可以存在
    CCTest();

}

//并行計算函數(shù)
kernel void CCTestKernelFunctionB(int a,int b)
{
    .....
}

//頂點函數(shù)
vertex int CCTestVertexFunctionB(int a,int b)
{
    .....
}

//片元函數(shù)
fragment int CCTestVertexFunctionB(int a,int b)
{
    .....
}

//普通函數(shù)
void CCTest()
{
    .....
}

變量、參數(shù)的地址空間修飾符

Metal著?器語?使?地址空間修飾符來表示?個函數(shù)變量或者參數(shù)變量被分配于那??內(nèi)存區(qū)域集漾。
地址空間修飾符

  • device:設(shè)備地址空間
  • threadgroup:線程組地址空間
  • constant:常量地址空間
  • thread: 線程地址空間

注意:

  • 所有的著色函數(shù)(vertex切黔、fragment、kernel)的參數(shù)具篇,指針或是引用類型的參數(shù)纬霞,都必須帶有地址空間修飾符號
  • 對于圖形著?器函數(shù), 其指針或是引?類型的參數(shù)必須定義為device 或是 constant 地址空間栽连。
  • 對于并行計算函數(shù)kernel修飾的函數(shù))险领,其指針或是引用類型的參數(shù)必須定義為 device、threadgroup秒紧、constant
/*
 注意:
 * 1\. 所有被(kernel,vertex,fragment)所修飾的參數(shù)變量,如果其類型是指針/引用都必須帶有地址空間修飾符.
 * 2\. 被fragment修飾的片元函數(shù), 指針/引用必須被device/constant/threadgroup
 */

//變量/參數(shù)地址空間修飾符
void CCTestFouncitionE(device int *g_data,
                       threadgroup int *l_data,
                       constant float *c_data
                       )
{
    //...
}

設(shè)備空間地址修飾符device

  • 設(shè)備地址空間(Device) 指向設(shè)備內(nèi)存池(顯存)中分配出來的緩存對象, 它可讀也是可寫; ?個緩存對象可 以被聲明成?個標(biāo)量、向量或是?戶?定義結(jié)構(gòu)體指針或是引?
  • device放在變量類型之前
// 設(shè)備地址空間: device 用來修飾指針.引用
//1.修飾指針變量
device float4 *color;

struct CCStruct{
    float a[3];
    int b[2];
};
//2.修飾結(jié)構(gòu)體類的指針變量
device CCStruct *my_CS;

注意:

  • device 除了可以修飾圖形著色器函數(shù) / 并行計算函數(shù)參數(shù)挨下,還可以修飾指針變量結(jié)構(gòu)體指針變量
  • 紋理對象總是在設(shè)備地址空間分配內(nèi)存,即GPU分配內(nèi)存
  • device地址空間修飾符不必出現(xiàn)在紋理類型定義中
  • 一個紋理對象的內(nèi)容無法直接訪問熔恢,Metal提供讀寫紋理的內(nèi)建函數(shù),通過內(nèi)建函數(shù)訪問紋理對象

線程組地址空間修飾符threadgroup

  • 線程組地址空間用于為并行計算著色器函數(shù)分配內(nèi)存變量臭笆,這些變量一個線程組的所有線程共享叙淌,在線程組地址空間分配的變量不能用于圖形繪制著色函數(shù)(即頂點/ 片元著色函數(shù))秤掌,即在圖形繪制著色函數(shù)不能使用線程組
  • 在并行計算著色函數(shù)中,在線程組地址空間分配變量為一個線程組使用鹰霍,生命周期和線程組相同
/*
 * 1\. threadgroup 被并行計算計算分配內(nèi)存變量, 這些變量被一個線程組的所有線程共享. 在線程組分配變量不能被用于圖像繪制.
 * 2\. thread 指向每個線程準(zhǔn)備的地址空間. 在其他線程是不可見切不可用的
 */
kernel void CCTestFouncitionF(threadgroup float *a)
{
    //在線程組地址空間分配一個浮點類型變量x
    threadgroup float x;

    //在線程組地址空間分配一個10個浮點類型數(shù)的數(shù)組y;
    threadgroup float y[10];

}

線程地址空間修飾符thread

  • 線程地址空間指向每個線程準(zhǔn)備的地址空間闻鉴,也是在GPU中,該線程的地址空間定義的變量其他線程不可見(變量不共享)
  • 圖形繪制著色函數(shù)或者并行計算著色函數(shù)中聲明的變量茂洒,在線程地址空間分配存儲
kernel void CCTestFouncitionG(void)
{
    //在線程空間分配空間給x,p
    float x;
    thread float p = &x;
}

常量地址空間修飾符constant

  • 常量地址空間指向的緩存對象也是從設(shè)備內(nèi)存池分配存儲孟岛,僅可讀
  • 程序域的變量必須定義在常量地址空間并且聲明時初始化,用來初始化的值必須是編譯時的常量
  • 程序域的變量生命周期和程序一樣督勺,在程序中的并行計算著色函數(shù) 或者 圖形繪制著色函數(shù)調(diào)用渠羞,但是constant的值會保持不變
constant float samples[] = { 1.0f, 2.0f, 3.0f, 4.0f };

//對一個常量地址空間的變量進行修改也會失敗,因為它只讀的
sampler[4] = {3,3,3,3}; //編譯失敗; 

//定義為常量地址空間聲明時不賦初值也會編譯失敗
constant float a;

注意:常量地址空間指針或是引?可以作為函數(shù)的參數(shù)。 向聲明為常量變量賦值會產(chǎn)?編譯錯誤智哀。聲明常量但是沒有賦予初值也會產(chǎn)?編譯錯誤

屬性修飾符 -- 函數(shù)參數(shù)與變量的傳遞修飾符

圖形繪制或者并?計算著?器函數(shù)的輸?輸出都是通過參數(shù)傳遞次询。除了常量地址空間變量程序域定義的采樣器以外

  • device buffer:設(shè)備緩存, ?個指向設(shè)備地址空間的任意數(shù)據(jù)類型的指針或者引?;
  • constant buffer: 常量緩存區(qū), ?個指向常量地址空間的任意數(shù)據(jù)類型的指針或引?
  • texture :紋理對象;
  • sampler :采樣器對象;
  • threadGrounp :在線程組中供各線程共享的緩存

屬性修飾符的目的

  • 參數(shù)表示資源的定位,可以理解為端口
  • 在固定管線和可編程管線進行內(nèi)建變量的傳遞
  • 將數(shù)據(jù)沿著渲染管線從頂點函數(shù)傳遞片元函數(shù).

傳遞修飾符在代碼中的使用

  • device buffer/constant buffer ---> [[buffer(index)]]
  • texture ---> [[texture(index)]]
  • sampler ---> [[sampler(index)]]
  • threadGroup ---> [[threadGroup(index)]]
    index是?個unsigned integer類型的值瓷叫,它表示了?個緩存屯吊、紋理、采樣器參數(shù)的位置(在函數(shù)參數(shù)索引 表中的位置)摹菠。 從語法上講盒卸,屬性修飾符的聲明位置應(yīng)該位于參數(shù)變量名之后
在代碼中如何表現(xiàn):
 1.已知條件:device buffer(設(shè)備緩存)/constant buffer(常量緩存)
 代碼表現(xiàn):[[buffer(index)]]
 解讀:不變的buffer ,index 可以由開發(fā)者來指定.

 2.已知條件:texture Object(紋理對象)
 代碼表現(xiàn): [[texture(index)]]
 解讀:不變的texture ,index 可以由開發(fā)者來指定.

 3.已知條件:sampler Object(采樣器對象)
 代碼表示: [[sampler(index)]]
 解讀:不變的sampler ,index 可以由開發(fā)者來指定.

 4.已知條件:threadgroup Object(線程組對象)
 代碼表示: [[threadgroup(index)]]
 解讀:不變的threadgroup ,index 可以由開發(fā)者來指定.

//并行計算著色器函數(shù)add_vectros ,實現(xiàn)2個設(shè)備地址空間中的緩存A與緩存B相加.然后將結(jié)果寫入到緩存out.
//屬性修飾符"(buffer(index))" 為著色函數(shù)參數(shù)設(shè)定了緩存的位置
//thread_position_in_grid:用于表示當(dāng)前節(jié)點在多線程網(wǎng)格中的位置,并不需要開發(fā)者傳遞,是Metal自帶的辨嗽。
/*
 kernel:并行計算函數(shù)修飾符
 void:函數(shù)返回值類型
 add_vectros:函數(shù)名
 const device float4 *inA [[buffer(0)]]:定義了一個float4類型的指針世落,指向一個4維向量空間,放在設(shè)備內(nèi)存空間(即顯存GPU中)
    - const device:只決定放在哪里
    - inA:變量名
    - [[buffer(0)]] 對應(yīng) buffer中0這個id
 */
kernel void add_vectros(
                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];
}

//著色函數(shù)的多個參數(shù)使用不同類型的屬性修飾符的情況
//紋理讀取的方式的sampler糟需,即采樣器屉佳,[[sampler(0)]]表示采樣器的緩存id
kernel void my_kernel(device float4 *p [[buffer(0)]],
                      texture2d<float> img [[texture(0)]],
                      sampler sam [[sampler(0)]])
{
    //.....

}

內(nèi)建變量修飾符

  • [[vertex_id]]:頂點id標(biāo)識符,不由開發(fā)者傳遞
  • [[position]]:在頂點函數(shù)中表示當(dāng)前的頂點信息--類型float4洲押,
    描述片元的窗口的相對坐標(biāo)(x武花,y,z杈帐,1/w),該像素點在屏幕上位置信息
  • [[point_size]]:點的大小体箕,類型是float
  • [[color(m)]]:顏色,m在編譯前就必須確定
  • [[stage_in]]?元著?函數(shù)使?的單個?元輸?數(shù)據(jù)是由頂點著?函數(shù)輸出然后經(jīng)過光柵化?成的挑童。頂點和?元著?函數(shù)都是只能有?個參數(shù)被聲明為使?stage_in修飾符累铅,對于?個使?了stage_in修飾符的?定義的結(jié)構(gòu)體,其成員可以為?個整形浮點標(biāo)量,或是整形浮點向量站叼。
//定義了片元輸入的結(jié)構(gòu)體娃兽,
struct MyFragmentOutput {
      // color attachment 0 顏色附著點0
     float4 clr_f [[color(0)]]; 
     // color attachment 1 顏色附著點1
     int4 clr_i [[color(1)]]; 
     // color attachment 2 顏色附著點2
     uint4 clr_ui [[color(2)]]; 
};

fragment MyFragmentOutput my_frag_shader( ... ) 
{
    MyFragmentOutput f;
    ....
    f.clr_f = ...;
    ....
    return f; 
}

作者:windy_3c22
鏈接:http://www.reibang.com/p/23c2b658d0f7

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市尽楔,隨后出現(xiàn)的幾起案子投储,更是在濱河造成了極大的恐慌第练,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件玛荞,死亡現(xiàn)場離奇詭異娇掏,居然都是意外死亡,警方通過查閱死者的電腦和手機勋眯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門婴梧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人凡恍,你說我怎么就攤上這事志秃。” “怎么了嚼酝?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵浮还,是天一觀的道長。 經(jīng)常有香客問我闽巩,道長钧舌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任涎跨,我火速辦了婚禮洼冻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘隅很。我一直安慰自己撞牢,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布叔营。 她就那樣靜靜地躺著屋彪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪绒尊。 梳的紋絲不亂的頭發(fā)上畜挥,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天,我揣著相機與錄音婴谱,去河邊找鬼蟹但。 笑死,一個胖子當(dāng)著我的面吹牛谭羔,可吹牛的內(nèi)容都是我干的华糖。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼瘟裸,長吁一口氣:“原來是場噩夢啊……” “哼缅阳!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起景描,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤十办,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后超棺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體向族,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年棠绘,在試婚紗的時候發(fā)現(xiàn)自己被綠了件相。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡氧苍,死狀恐怖夜矗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情让虐,我是刑警寧澤紊撕,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站赡突,受9級特大地震影響对扶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜惭缰,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一浪南、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧漱受,春花似錦络凿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至紧憾,卻和暖如春到千,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背赴穗。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工憔四, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人般眉。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓了赵,卻偏偏與公主長得像,于是被迫代替她去往敵國和親甸赃。 傳聞我的和親對象是個殘疾皇子柿汛,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容