Cg(C for Graphic)語言表達式與控制語句

摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU編程與CG語言之陽春白雪下里巴人” 


 

在上一章中,我們已經介紹了 Cg 語言的基礎數據類型( 7 種)、內置數據類型,以及數組、結構、接口等類型,本章將在此基礎上討論 Cg 中的表達式,表達式由操作符( operator )關聯一個或多個操作數( operand )構成,我們首先闡述各種類型的操作符,並結合數據類型講解操作符的具體使用方法。

Cg 中的操作符與 C 語言中的類似(操作符的功能和寫法與 C 相同,但用法不盡相同),按照操作符的功能可以劃分爲:關係操作符、邏輯操作符、條件操作符。 Cg 中有一類較爲獨特的操作符,稱爲 Swizzle 操作符, 這個操作符用於取出向量類型變量中的分量。此外,與 C 語言不同的是, Cg 允許在向量類型變量上使用操作符,例如 > 操作符可以用來比較兩個向量各個分量的大小關係。 Cg 中的表達式還有很多與 C 語言不同的細節之處,將在本章中一一分說。

6.1 關係操作符( Comparison Operators

關係操作符,用於比較同類型數據(不同類型的基礎數據需要進行類型轉換,不同長度的向量,不能進行比較)之間的大小關係或者等價關係。 Cg 中有 6 種關係操作符,如 1 所示 , 關係操作符運算後的返回類型均爲 bool 類型。

關係操作符

 

功能

用法

小於

expr < expr

<=

小於或等於

expr <= expr

!=

不等於

expr != expr

==

 

等於

expr == expr

>=

大於或等於

expr >= expr

大於

expr > expr

1 關係操作符

Cg 中,由於關係操作符以及下節會講到的邏輯操作符,都返回 bool 類型結果,所以這兩種操作符有時也被統一稱爲 boolean operator

Cg 語言表達式允許對向量使用所有的 boolean operator ,如果是二元操作符,則被操作的兩個向量的長度必須一致。表達式中向量的每個分量都進行一對一的運算,最後返回的結果是一個 bool 類型的向量,長度和操作數向量一致。例如:

 

float3 a = float4(0.5, 0.0, 1.0);

float3 b = float4(0.6, -0.1, 0.9);

bool3 c = a<b;

運算後向量 c 的結果爲 float3(true, false, true);

6.2 邏輯操作符( Logical Operators

Cg 語言中有 3 種邏輯操作符 ( 也被稱爲 boolean Operators) ,如 2 所示,邏輯操作符運算後的返回類型均爲 bool 類型。

邏輯操作符

 

功能

用法

&&

邏輯與

expr && expr

||

邏輯或

expr || expr

!

邏輯非

!expr

2 邏輯操作符

正如上節所說,邏輯操作符也可以對向量使用,返回的變量類型是同樣長度的內置 bool 向量。

有一點需要注意: Cg 中的邏輯與( && )和邏輯或( || )不存在 C 中的短路現象( short-circuiting ,即只用計算一個操作數的 bool 值即可),而是參與運算的操作數據都進行 bool 分析。

6.3 數學操作符( Math Operators

Cg 語言對向量的數學操作提供了內置的支持, Cg 中的數學操作符有: * 乘法; / 除法; - 取反; + 加法;—減法; % 求餘; ++ ;——; *= /= += -= ;後面四種運算符有時被歸納入賦值操作符,不過它們實際上進行數學計算,然後進行賦值,所以這裏也放入數學操作符中進行說明。

  在文獻【 2 】第 3.3 Math Expressions 中,其行文意思容易讓人覺得“好像只有加減乘除等運算可以對向量進行”,實際上經過我的測試, ++ 、——等數學運算符同樣可以使用在向量上。所以“ Cg 語言對向量的數學操作提供內置支持”這句話是非常準確的。

需要注意的是:求餘操作符 % 。只能在 int 類型數據間進行,否則編譯器會提示錯誤信息: error C1021: operands to % must be integral.

當使用這些數學操作符對一個標量和一個向量進行運算時,標量首先被複制到一個長度相同的向量中,然後進行運算,例如下面的代碼形式是正確的:

 

void function()

{

       float2 a = float2(1.0, 1.0);

 

    float b = 2.0;

      

       f *= d;

       f *= 2.0;

}

6.4 移位操作符

Cg 語言中的移位操作符,功能和 C 語言中的一樣,也可以作用在向量上,但是向量類型必須是 int 類型。例如:

 

int2 a = int2(0.0,0.0);

int2 b = a>>1;

 

如果使用如下代碼,會出現錯誤提示信息: error C1021:operands to shr must be integral.

 

float2 a = int2(0.0,0.0);

float2 b = a>>1;

 

 

6.5 Swizzle 操作符

可以使用 Cg 語言中的 swizzle 操作符( . )將一個向量的成員取出組成一個新的向量。 swizzle 操作符被 GPU 硬件高效支持。 swizzle 操作符後接 x y z w ,分別表示原始向量的第一個、第二個、第三個、第四個元素; swizzle 操作符後接 r g b a 的含義與前者等同。不過爲了程序的易讀性,建議對於表示顏色值的向量,使用 swizzle 操作符後接 r g b a 的方式。

舉例如下:

 

float4(a, b, c, d).xyz    等價於   float3(a, b, c)

float4(a, b, c, d).xyy    等價於   float3(a, b, b)

float4(a, b, c, d).wzyx   等價於   float4(d, c, b, a)

float4(a, b, c, d).w      等價於   float d

 

值得注意的是, Cg 語言中 float a float1 a 是基本等價的,兩者可以進行類型轉換; float bool half 等基本類型聲明的變量也可以使用 swizzle 操作符。例如:

 

float a = 1.0;

float4 b = a.xxxx;

注意: swizzle 操作符只能對結構體和向量使用,不能對數組使用,如果對數組使用 swizzle 操作符則會出現錯誤信息: error C1010: expression left of . x is not a struct or array (其實個人覺得,提示的錯誤信息中 array 換成 vector 更加合適)。

  要從數組中取值必須使用 [] 符號。例如:

 

float a[3] = {1.0,1.0,0.0};

float b = a[0]; // 正確

float c = a.x; // 編譯會提示錯誤信息

 

6.6 條件操作符( Conditional Operators

條件操作符的語法格式爲:

                                     expr1 ? expr2 : expr3;

expr1 的計算結果爲 true 或者 flase ,如果是 true, expr2 執行運算,否則 expr3 被計算。

條件操作符爲簡單的 if-else 語句提供了一種便利的替代方式,例如我們可以不必寫:

 

if(a < 0){b = a}

else{c = a}

 

而改寫爲:

                        a < 0 ?(b = a) :( c = a);

Cg 中的條件操作符一個獨特的性能是:支持向量運算。即, expr1 的計算結果可以是 bool 型向量, expr2 expr3 必須是與 expr1 長度相同的向量。舉例如下:

 

float3 h = float3(-1.0,1.0,1.0);

float3 i = float3(1.0,0.0,0.0);

float3 g = float3(1.0,1.0,0.0);

float3 k;

      

k = (h < float3(0.0,0.0,0.0))?(i):(g);

  三元向量 h float3(0.0, 0.0, 0.0) 做比較運算後結果爲( true, false, false , 所以 i 的第一個數據賦值給 K 的第一個數據, g 的第二個和第三個數據賦值給 k 的第二個和第三個數據, K 的值爲 (1.0, 1.0, 0.0)

6.7 操作符優先順序

Cg 語言中操作符的優先順序如 3 所示,從上到下表示從高級到低級的優先級;同一行的操作符具有同等優先級。該表參考了 Cg 教程 _ 可編程實時圖形權威指南第 3.3.1 節。

操作符

 

結合律

功能

() [] -> .

從左到右

函數調用、數組引用、結構引用、成員選擇

! ~ ++ - + - * & (type) sizeof

從右到左

一元操作符:取反、增加、減少、正號、負號、間接、地址、轉換

* / %

從左到右

乘法、除法、餘數

+ -

從左到右

加法、減法

<<  >>

從左到右

移位操作符

< >= > >=

從左到右

關係操作符

==  !=

從左到右

等於,不等

&

從左到右

位操作符與

^

從左到右

位操作符異或

|

從左到右

位操作符或

&&

從左到右

邏輯與

||

從左到右

邏輯或

?:

從右到左

條件表達式

= += -= *= /= %= &= ^= != <<= >>=

從右到左

賦值、賦值表達式

,

從左到右

逗號操作符

3 操作符優先級

 

6.8 控制流語句( Control Flow Statement

程序最小的獨立單元是語句( statement ),語句一般由分號結尾,缺省情況下,語句是順序執行的,但是當涉及邏輯判斷控制時,就要求有控制流程序語句。控制流程序語句分爲條件語句和循環語句,在 C 語言中,條件語句有 if if-else switch 等,而循環過程則由 while do-while for 語句支持。 Cg 中的控制流語句和循環語句與 C 語言類似:條件語句有: if if-else ;循環語句有: while for break 語句可以和在 for 語句中使用。

Cg 語言中的控制流語句要求其中的條件表達式返回值都是 bool 類型,這一點是與 C 語言不同之處( C 語言中,條件表達式返回值可以是 0 1

vs_2_x, vp30 vp40 這些 profile 支持分支指令(又稱轉移指令, branch instruction ), for while 循環指令在這些 profile 中被完全支持。在文獻【 3 】中提到:

In other profiles, for and while loops may only be used if the compiler can fully unroll them (that is, if the compiler can determine the iteration count at compile time) ”。

這句話的意思是“在其他的 profiles 中, for while 循環只有當確切的知道循環次數時才能被使用”。但經過試驗,如果使用“在 fp40 ps_3_0 之前的” 片段 profiles 編譯含義 for, while 語句時會出現錯誤提示信息: error c6003 instruction limit of exceeded …… 。因此,如果沒有確切的把握,不要在低級的 profiles 中使用循環控制語句。

同樣, return 只能作爲最後一條語句出現。函數的遞歸調用( recursion )在 Cg 語言中是被禁止的。 Switch case default Cg 中作爲保留關鍵字存在,但是它們目前不被任何 profile 所支持。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章