目錄
6.1 函數定義
如上面的語法所示,有效着色器是一系列全局聲明和函數定義。 聲明一個函數,如下例所示:
// prototype
returnType functionName (type0 arg0, type1 arg1, ..., typen argn);
而函數定義如下:
// definition
returnType functionName (type0 arg0, type1 arg1, ..., typen argn)
{
// do some computation
return returnValue;
}
其中returnType必須存在且包含類型。 每個typeN必須包含一個類型,並且可以選擇包括參數限定符,const和精度限定符。
通過使用其名稱後跟括號中的參數列表來調用函數。
允許數組作爲參數,但不允許作爲返回類型。 當數組聲明爲形式參數時,必須包含它們的大小。通過使用數組名稱而不使用任何下標或括號將數組傳遞給函數,並且傳入的數組參數的大小必須與形式參數聲明中指定的大小匹配。
結構也被允許作爲參數。 如果結構不包含數組,則返回類型也可以是結構。
有關聲明和定義函數的語法的權威性參考,請參見第9節“着色語言語法”。
所有函數必須使用原型聲明,或者在調用之前使用帶有方法體的方式定義。例如:
float myfunc (float f, // f is an input parameter
out float g); // g is an output parameter
函數聲明必須指定返回類型。 此類型可能void。 如果返回類型不是void,則函數定義中的任何return語句都必須包含return表達式,並且表達式的類型必須與返回類型匹配。 如果函數的返回類型指定爲void,則任何此類return語句都不能包含return表達式。不接受輸入參數的函數不需要在參數列表中使用void,因爲原型(或定義)是必需的,因此當聲明空參數列表“()”時沒有歧義。 爲方便起見,提供了作爲參數列表的約定俗成的表達“(void)”
函數名稱可以重載。 這允許相同的函數名稱用於多個函數,只要參數列表類型不同即可。如果函數的名稱和參數類型匹配,則它們的返回類型和參數限定符也必須匹配。 函數簽名匹配僅基於參數類型,不使用限定符。 重載在內置函數中使用很多。 當解析重載函數(或實際上任何函數)時,尋求函數簽名的精確匹配。 這包括數組大小的精確匹配。 不會對返回類型或輸入參數類型進行升級或降級。 必須將所有預期的輸入和輸出組合定義爲單獨的功能。
例如,內置點乘函數具有以下原型:
float dot (float x, float y);
float dot (vec2 x, vec2 y);
float dot (vec3 x, vec3 y);
float dot (vec4 x, vec4 y);
用戶定義的函數可以有多個聲明,但只有一個定義。
函數main用作着色器的入口點。 頂點着色器和片段着色器都必須包含名爲main的函數。 此函數不帶參數,不返回任何值,並且必須聲明爲void類型:
void main()
{
...
}
函數main可以包含return的用法。 更多詳細信息,請參見第6.4節“跳轉”。
使用任何其他簽名聲明名爲main的函數是錯誤的。
6.1.1 函數調用慣例
函數由value-return調用。 這意味着輸入參數在調用時被複制到函數中,輸出參數在函數退出之前被複制回調用者。 因爲該函數適用於參數的本地副本,所以在函數中沒有關於變量別名的問題。
要控制通過函數定義或聲明覆制和/或複製的參數:
- 關鍵字in用作限定符,表示要複製進的參數,但不能複製出去。
- 關鍵字out用作限定符,表示要複製出的參數,但不能複製進。這個應該儘可能的使用,以避免不必要地複製參數。
- 關鍵字inout用作限定符,表示要複製進和複製出去的參數。
- 聲明沒有以上的限定符的函數參數意味着與指定in相同。
所有參數在調用時按順序從左到右進行計算。對in參數只是複製其形式參數,而out參數則是在函數返回時將值賦值給它,而inout參數則是在調用時複製其作爲形式參數的值進行計算,在函數返回時則將值賦值給它。
輸出參數複製回調用方的順序未定義。
在函數中,僅輸入參數是允許被寫入的。 只是函數的副本被修改了。 這個問題可以通過使用const限定符聲明參數來防止。
調用函數時,不計算爲左值的表達式不能傳遞給聲明爲out或inout的參數。
如果函數未寫入out參數,則函數返回時,實際參數的值表現爲未定義的。
如果使用非void返回類型聲明函數並且函數返回而不執行return語句,則返回的值是未定義的。
在函數的返回類型上只允許使用精度限定符來修飾。
結構聲明不允許作爲參數聲明或返回類型聲明的一部分。
函數原型:
精度修飾符 類型 方法名(const修飾符 參數修飾符 精度修飾符 類型 名稱 數組修飾符)
類型:
基礎類型,結構名稱,或結構定義
const修飾符:
空
const
參數修飾符:
空
in
out
inout
名稱:
空
自定義
數組修飾符:
空
[數組長度]
但是,const限定符不能與out或inout一起使用。以上用於函數聲明(即原型)和函數定義。 因此,函數定義可以具有未命名的參數(但是在實現方法的時候是需要有參數名的)。
不允許靜態和動態遞歸,(很多底層芯片沒有實現)。