2012-01-09 56 views
2

我的一個新着色器出現問題。OpenGL ES 2.0 NVIDIA TEGRA 2展開

當我在不同的設備上嘗試着色器時,着色器編譯並順利運行。

當我嘗試它的的NVIDIA Tegra 2的GPU,運行本地代碼,我得到以下編譯錯誤:

着色器無法編譯。頂點着色器 (0):錯誤C6002:超過指令限制256; 532條指令需要編譯程序 86行,1個錯誤。

我認爲這是由於NVIDIA的gcg編譯器執行某種類型的展開,但我無法弄清楚如何解決這種情況。

現在,我試圖減少if/else語句的類型,而不是if/else,而是一連串簡單的連續ifs(只是爲了查看問題是否已解決),但它不起作用。

我試圖刪除所有的條件,只留下一個和着色器編譯良好(儘管它沒有做我真正需要的)。

這是我的頂點着色器的代碼,片段着色器只包含gl_color信息並編譯良好。

void main(){ 

//Converto direttamente in int, cosi le divisioni dopo sono piu veloci 
int_character_position = int(character_position); 

uniform_reference = (int_character_position/4); 

uniform_reference_sub_item = int(mod(character_position,4.0)); 

if(uniform_reference == 0) {   
    working_float = charsequence_1[uniform_reference][uniform_reference_sub_item];  
} else if(uniform_reference == 1) {  
    working_float = charsequence_1[uniform_reference][uniform_reference_sub_item];    
} else if(uniform_reference == 2) { 
    working_float = charsequence_1[uniform_reference][uniform_reference_sub_item]; 
} else if(uniform_reference == 3) { 
    working_float = charsequence_1[uniform_reference][uniform_reference_sub_item]; 
} else if(uniform_reference == 4) { 
    working_float = charsequence_2[uniform_reference - 4][uniform_reference_sub_item]; 
} else if(uniform_reference == 5) { 
    working_float = charsequence_2[uniform_reference - 4][uniform_reference_sub_item]; 
} else if(uniform_reference == 6) { 
    working_float = charsequence_2[uniform_reference - 4][uniform_reference_sub_item]; 
} else if(uniform_reference == 7) { 
    working_float = charsequence_2[uniform_reference - 4][uniform_reference_sub_item]; 
} else if(uniform_reference == 8) { 
    working_float = charsequence_3[uniform_reference - 8][uniform_reference_sub_item]; 
} else if(uniform_reference == 9) { 
    working_float = charsequence_3[uniform_reference - 8][uniform_reference_sub_item]; 
} else if(uniform_reference == 10) { 
    working_float = charsequence_3[uniform_reference - 8][uniform_reference_sub_item]; 
} else if(uniform_reference == 11) { 
    working_float = charsequence_3[uniform_reference - 8][uniform_reference_sub_item]; 
} else if(uniform_reference == 12) { 
    working_float = charsequence_4[uniform_reference -12][uniform_reference_sub_item]; 
} else if(uniform_reference == 13) { 
    working_float = charsequence_4[uniform_reference -12][uniform_reference_sub_item]; 
} else if(uniform_reference == 14) { 
    working_float = charsequence_4[uniform_reference -12][uniform_reference_sub_item]; 
} else if(uniform_reference == 15) { 
    working_float = charsequence_4[uniform_reference -12][uniform_reference_sub_item]; 
} else if(uniform_reference == 16) { 
    working_float = charsequence_5[uniform_reference -16][uniform_reference_sub_item]; 
} else if(uniform_reference == 17) { 
    working_float = charsequence_5[uniform_reference -16][uniform_reference_sub_item]; 
} else if(uniform_reference == 18) { 
    working_float = charsequence_5[uniform_reference -16][uniform_reference_sub_item]; 
} else if(uniform_reference == 19) { 
    working_float = charsequence_5[uniform_reference -16][uniform_reference_sub_item]; 
} else if(uniform_reference == 20) { 
    working_float = charsequence_6[uniform_reference -20][uniform_reference_sub_item]; 
} else if(uniform_reference == 21) { 
    working_float = charsequence_6[uniform_reference -20][uniform_reference_sub_item]; 
} else if(uniform_reference == 22) { 
    working_float = charsequence_6[uniform_reference -20][uniform_reference_sub_item]; 
} else if(uniform_reference == 23) { 
    working_float = charsequence_6[uniform_reference -20][uniform_reference_sub_item]; 
}     
v_texCoord.y = a_texture.y; 
v_texCoord.x = a_texture.x + (0.0105 * float(working_float)); 
gl_Position = myMVPMatrix * myVertex; 

回答

2

OpenGL ES 2.0的實施方案中通常具有它們支持的指令的最大數量,但由於它是不切實際的最小數目不被授權的API。 Nvidia Tegra實現將源代碼編譯爲532條指令,該指令超出了其最大限制。除了修改OpenGL ES 2.0實現之外,唯一可能的方法是重寫着色器,以便將其編譯爲更少的指令。

如果不知道Nvidia實現的細節,像working_float = charsequence_6[uniform_reference -20][uniform_reference_sub_item];這樣的語句與分支結合在一起會產生多條指令(您有減法,加載,存儲和數組索引)。一般來說分支通常是有問題的,因爲由於不同的代碼流,編譯器可能無法編譯多條指令並行運行。

你如果 - 否則,如果 - 否則,如果代碼是很容易改寫,以便它可以被編譯成更小的指令,同時仍具有相同的含義:

if(uniform_reference < 4) {   
    working_float = charsequence_1[uniform_reference][uniform_reference_sub_item]; 
} else if(uniform_reference < 8) { 
    working_float = charsequence_2[uniform_reference - 4][uniform_reference_sub_item]; 
} else if(uniform_reference < 12) { 
    working_float = charsequence_3[uniform_reference - 8][uniform_reference_sub_item]; 
} else if(uniform_reference < 16) { 
    working_float = charsequence_4[uniform_reference -12][uniform_reference_sub_item]; 
} else if(uniform_reference < 20) { 
    working_float = charsequence_5[uniform_reference -16][uniform_reference_sub_item]; 
} else if(uniform_reference < 24) { 
    working_float = charsequence_6[uniform_reference -20][uniform_reference_sub_item]; 
} 

可能已裝配到256指令限制。 (在着色器代碼中,規則的大拇指通常只是GLSL代碼的大小,粗略定義了指令的數量。)如果不是這樣,看起來您可以將uniform_reference - {4,8,etc}替換爲uniform_reference_sub_item,因爲它似乎是相同的值;這也會節省一些說明。最終,你可以把charsequence_ [123456]值到一個數組和索引它的基礎上uniform_reference一個常數,還有的CharSequence劃分,而不是,所以,到底你有這樣的事情:

working_float = charsequence[uniform_reference/4][uniform_reference - uniform_reference_sub_item][uniform_reference_sub_item]; 

也許你也可以合併由uniform_referenceuniform_reference_sub_item索引的兩個數組以排除一個索引級別。

+0

非常感謝。在我發佈了我的請求之後,我已經相應地修改了我的if語句,並且我正在此處針對該問題的解決方案更新社區。 無論如何,您的回答非常好。非常感謝你的協助。着色器代碼是一個相當原型,最終它遠比實際要求的要複雜得多:) 非常感謝。 – 2012-01-09 20:57:06