Penso di avere quello che stai cercando di chiedere. Presumo che la tua preoccupazione principale siano le variabili non uniformi definite al di fuori di main()
:
float left;
float right;
float mscaled;
float xn;
float xm;
Diamo un'occhiata a come funzionano GPU e GLSL. La GPU non ha uno stack o record di attivazione delle chiamate. Non esiste un modo per simulare l'ambito o le variabili locali in GLSL come un compilatore C può fare sulla maggior parte delle CPU. Tutto ciò che esiste sono i registri, che sono registri uniformi, input dello stadio shader, output e il file di registro locale univoco per quella chiamata shader.
In altre parole, poiché non esiste una funzione, uno stack o un heap, tutte le variabili dichiarate ovunque vivono in un registro. Che siano locali in un certo ambito in GLSL o globali nell'intero file non fa alcuna differenza. Sono solo registri.
Tuttavia, l'allocatore di registro non fa parte dello standard GLSL. Diverse implementazioni OpenGL possono avere diversi livelli di qualità quando si tratta di convertire il codice GLSL di alto livello nel codice macchina di basso livello che la GPU comprende. Una delle parti più complicate di un compilatore (GLSL o altro) è l' allocazione dei registri . Questa è la parte del compilatore che determina quali registri occupa una determinata variabile. C ha un po 'più difficile in quanto di solito ha a che fare con file di registro molto piccoli (specialmente su x86) e deve occuparsi dello spargimento del registro (spostare le variabili nello stack) e dell'aliasing (salvare le variabili nella RAM prima di chiamare le funzioni) e istruzioni dispari che richiedono che l'output sia in un registro particolare (x86idiv
per esempio). Le GPU hanno un file di registro di grandi dimensioni a causa della mancanza di stack o heap, quindi l'allocatore può essere più semplice.
Tuttavia, il file di registro non è infinito. Se hai più variabili dei registri supportati dal tuo hardware, il compilatore dovrà provare ad adattare tutte le tue variabili ai registri. Questo di solito richiede una qualche forma di controllo dell'intervallo di liveness . Cioè, se usi una variabile xn
per un calcolo e non la usi mai più, il compilatore può determinarlo e quindi sapere che il registro occupato xn
potrebbe essere usato in seguito da un'altra variabile, permettendo così più variabili di quante ce ne siano dei registri (così a lungo poiché non ci sono troppe variabili attive contemporaneamente).
Il compilatore potrebbe non farlo, tuttavia. Non ha. O potrebbe farlo solo in alcuni casi. Gli ambiti forniti ai compilatori più semplici rappresentano un problema molto più semplice da risolvere. Tutti i registri assegnati alle variabili di funzione locali possono essere riutilizzati dopo che quella funzione è uscita perché sa che le variabili sono morte. Le variabili globali non hanno una garanzia così facile. Quindi, alcuni compilatori meno capaci potrebbero non ottimizzare anche la loro vita e le variabili globali mangeranno sempre un registro. Ciò non rallenta nulla, ma in alcuni driver può limitare la dimensione dello shader che è possibile scrivere.
In generale, consiglio vivamente di mantenere localizzate tutte le variabili. Mantieni la definizione il più vicino possibile all'utilizzo della variabile. Questo vale per tutti i linguaggi di programmazione, non solo per GLSL. Vorrei anche raccomandare di rendere ogni const "variabile" in ogni caso possibile. Ancora una volta può essere un suggerimento per alcuni compilatori meno capaci che alcune ottimizzazioni siano possibili e, cosa ancora più importante, rende il codice più autocompattante e facile da mantenere.
E, naturalmente, ecco il tuo consiglio "solo profilo da testare e scoprire con certezza". Scrivi il tuo shader con e senza i tuoi globi e profilalo. Tutti i consigli sulle prestazioni online devono essere diffidati e devono essere impregnati di supposizione o non aggiornati.
main()
funzione? I tuoi valori sono in realtà variabili globali (uniformi o attributi nel linguaggio GLSL) o valori costanti?