2013-09-01 12 views
8

Il mio 9600GT mi odia.Lo shader GLSL non si srotola quando necessario

Fragment Shader:

#version 130 

uint aa[33] = uint[33](
    0,0,0,0,0,0,0,0,0,0, 
    0,0,0,0,0,0,0,0,0,0, 
    0,0,0,0,0,0,0,0,0,0, 
    0,0,0 
); 

void main() { 
    int i=0; 
    int a=26; 

    for (i=0; i<a; i++) aa[i]=aa[i+1]; 

    gl_FragColor=vec4(1.0,0.0,0.0,1.0); 

} 

Se a=25 programma viene eseguito a 3000 fps.
Se il programma a=26 viene eseguito a 20 fps.
Se la dimensione di aa < = 32 il problema non viene visualizzato.
La dimensione della vista è 1000x1000.
Il problema si verifica solo quando la dimensione di aa è> 32.
Valore di a poiché la soglia varia con le chiamate all'array all'interno del ciclo (aa[i]=aa[i+1]+aa[i-1] dà una scadenza diversa).
Lo so gl_FragColor è deprecato. Ma non è questo il problema.

La mia ipotesi è che GLSL non srotoli automaticamente il ciclo se a> 25 e dimensione (aa)> 32. Perché. Il motivo per cui dipende dalla dimensione dell'array è sconosciuto all'umanità.

Un comportamento molto simile spiegato qui:
http://www.gamedev.net/topic/519511-glsl-for-loops/

svolgimento del ciclo non manualmente risolvere il problema (3000 fps), anche se aa dimensione è> 32:

aa[0]=aa[1]; 
    aa[1]=aa[2]; 
    aa[2]=aa[3]; 
    aa[3]=aa[4]; 
    aa[4]=aa[5]; 
    aa[5]=aa[6]; 
    aa[6]=aa[7]; 
    aa[7]=aa[8]; 
    aa[8]=aa[9]; 
    aa[9]=aa[10]; 
    aa[10]=aa[11]; 
    aa[11]=aa[12]; 
    aa[12]=aa[13]; 
    aa[13]=aa[14]; 
    aa[14]=aa[15]; 
    aa[15]=aa[16]; 
    aa[16]=aa[17]; 
    aa[17]=aa[18]; 
    aa[18]=aa[19]; 
    aa[19]=aa[20]; 
    aa[20]=aa[21]; 
    aa[21]=aa[22]; 
    aa[22]=aa[23]; 
    aa[23]=aa[24]; 
    aa[24]=aa[25]; 
    aa[25]=aa[26]; 
    aa[26]=aa[27]; 
    aa[27]=aa[28]; 
    aa[28]=aa[29]; 
    aa[29]=aa[30]; 
    aa[30]=aa[31]; 
    aa[31]=aa[32]; 
    aa[32]=aa[33]; 
+0

Allora ... qual è la tua domanda? –

+1

@NicolBolas Perché quando a = 26 framerate scende drasticamente? – user2464424

+1

L'unica persona che saprebbe che è la persona che ha implementato il compilatore OpenGL. –

risposta

5

sto solo mettendo in una risposta riassuntiva dei commenti qui così questo non si presenta più come senza risposta.

"#pragma optionNV (srotolare tutti)"

risolve il problema immediato sulle nvidia.

In generale, tuttavia, i compilatori GLSL sono molto dipendenti dall'implementazione. Il motivo per cui c'è un calo di esattamente a 32 è facilmente spiegabile colpendo un euristico del compilatore come "non srotolare i loop più lunghi di 32". Inoltre, l'enorme differenza di velocità potrebbe provenire da un ciclo srotolato utilizzando le costanti mentre un ciclo dinamico richiederà una memoria di array indirizzabile. Un altro motivo potrebbe essere che durante lo srotolamento dell'eliminazione del codice morto, un calcio di piegamento costante riduce l'intero ciclo a zero.

Il modo più semplice per risolvere questo problema è lo srotolamento manuale o la piegatura costante manuale. È sempre discutibile calcolare le costanti in uno shader di frammenti che può essere calcolato all'esterno. Alcuni driver potrebbero prenderlo per alcuni casi, ma è meglio non fare affidamento su questo.

+1

Farò notare che la lunghezza del loop è 26, non 32. 32 è la dimensione dell'array. Fondamentalmente, questo è un caso estremo infernale. Ci sono almeno 3 fattori in conflitto tra loro: 1) compilatore che cancella il codice morto solo se il ciclo è srotolato. 2) array costante che si trasforma in un array assegnato alla VRAM dopo 32 float. 3) la soglia di lunghezza del loop prima che venga srotolata automaticamente dipende dai tipi di variabile coinvolti nel loop stesso. Conclusione: nessuno dovrebbe mai accadere in questo caso, poiché il codice che ho postato è una pratica molto negativa e non dovrebbe mai essere usato in nessuno scenario del mondo reale. – user2464424

Problemi correlati