Cela aide-t-il à déclarer des variables en dehors de la portée de votre fonction principale dans GLSL? Ces variables sont-elles réellement réutilisées et est-elle plus efficace?
Voici le code en question:
varying vec2 vposition;
uniform float seed;
uniform float top;
uniform float bottom;
uniform float phi;
uniform float theta;
uniform float scaledPI;
uniform float yn;
uniform float ym;
uniform float rx;
uniform float ry;
uniform float radius;
const float PI = 3.141592653589793238462643383;
float left;
float right;
float mscaled;
float xn;
float xm;
void main() {
float t = vposition.y * yn + ym;
if(t <= 0.0 || t >= PI){
left = phi - PI;
right = phi + PI;
}else{
mscaled = scaledPI / (1 - abs(Math.cos(theta)));
mscaled = mscaled < PI ? mscaled : PI;
left = phi - mscaled;
right = phi + mscaled;
}
xn = (left - right) / ((-rx / 2.0) - (rx / 2.0));
xm = left - ((-rx/2.0) * xn);
float p = vposition.x * xn + xm;
vec3 coords = vec3( sin(p) * sin(t), cos(t), cos(p) * sin(t) );
float nv = surface( vec4( coords, seed ) );
gl_FragColor = vec4( vec3( nv, nv, nv ), 1.0 );
}
main()
fonction? Vos valeurs sont-elles réellement des variables globales (uniformes ou attributs dans le langage GLSL) ou des valeurs constantes?Réponses:
Je pense que je comprends ce que vous essayez de demander. Je suppose que votre principale préoccupation concerne les variables non uniformes définies en dehors de
main()
:Jetons un coup d'œil au fonctionnement du GPU et du GLSL. Le GPU n'a pas de pile ni d'enregistrements d'activation d'appel. Il n'y a aucun moyen de simuler la portée ou les variablaes locales dans GLSL comme un compilateur C peut le faire sur la plupart des CPU. Tout ce qui existe, ce sont les registres, qui sont soit des registres uniformes, des entrées, des sorties d'étage de shader et le fichier de registre local propre à cette invocation de shader.
En d'autres termes, comme il n'existe pas de fonction, de pile ou de tas, toutes les variables déclarées n'importe où vivent dans un registre. Qu'ils soient locaux à une certaine étendue dans GLSL ou globaux à l'ensemble du fichier ne fait aucune différence. Ce ne sont que des registres.
Cependant, l'allocateur de registre ne fait pas partie de la norme GLSL. Différentes implémentations OpenGL peuvent avoir différents niveaux de qualité lorsqu'il s'agit de convertir du code GLSL de haut niveau en code machine de bas niveau que le GPU comprend. L'une des parties les plus compliquées d'un compilateur (GLSL ou autre) est l' allocation des registres . C'est la partie du compilateur qui détermine quels registres une variable donnée occupe. C a un peu plus de difficulté car il doit généralement gérer de très petits fichiers de registre (en particulier sur x86) et il doit gérer le débordement de registre (déplacement des variables vers la pile) et l'alias (sauvegarde des variables dans la RAM avant d'appeler des fonctions) et des instructions impaires qui demandent que la sortie soit dans un registre particulier (x86
idiv
par exemple). Les GPU ont un fichier de registre de grande taille en raison de l'absence de pile ou de tas, donc l'allocateur peut être plus simple.Cependant, le fichier de registre n'est pas infini. Si vous avez plus de variables que de registres pris en charge par votre matériel, le compilateur devra essayer d'ajuster toutes vos variables dans les registres. Cela nécessite généralement une forme de vérification de la plage de vie . Autrement dit, si vous utilisez une variable
xn
pour un calcul, puis ne l'utilisez plus jamais, le compilateur peut le déterminer et savoir que le registre occupé parxn
pourrait être utilisé par une autre variable plus tard, permettant ainsi plus de variables qu'il n'y a de registres (si longtemps car il n'y a pas trop de variables live à la fois).Cependant, le compilateur peut ne pas le faire. Ce n'est pas le cas. Ou il pourrait ne le faire que dans certains cas. Les étendues données aux compilateurs plus simples sont un problème beaucoup plus facile à résoudre. Tous les registres alloués aux variables de fonction locales peuvent être réutilisés après la fermeture de cette fonction car elle sait que les variables sont mortes. Les variables globales n'ont aucune garantie aussi simple. Par conséquent, certains compilateurs moins capables peuvent ne pas optimiser également leur durée de vie, et les variables globales consomment toujours un registre. Cela ne fera pas quoi que ce soit plus lent , mais il peut sur certains pilotes limiter la taille du shader , vous pouvez écrire.
En général, je recommande fortement de garder toutes les variables localisées. Gardez la définition aussi proche que possible de l'utilisation de la variable. Cela s'applique à tous les langages de programmation, pas seulement à GLSL. Je recommanderais également de faire chaque const "variable" dans tous les cas que vous pouvez. Il peut encore être un indice pour certains compilateurs moins capables que certaines optimisations sont possibles, et plus important encore, cela rend votre code plus auto-documenté et facile à maintenir.
Et bien sûr, voici votre "profil juste obligatoire pour tester et découvrir avec certitude" des conseils. Écrivez votre shader avec et sans vos globales et profilez-le. Tous les conseils de performance en ligne doivent être méfiants et supposés être imprégnés de suppositions ou obsolètes.
la source