Creo que entiendo lo que intentas preguntar. Supongo que su principal preocupación son las variables no uniformes definidas fuera de main()
:
float left;
float right;
float mscaled;
float xn;
float xm;
Echemos un vistazo a cómo funcionan la GPU y GLSL. La GPU no tiene una pila ni registros de activación de llamadas. No hay una manera de simular el alcance o las variables locales en GLSL como un compilador de C puede hacer en la mayoría de las CPU. Todo lo que existe son los registros, que son registros uniformes, entradas de etapa de sombreador, salidas y el archivo de registro local exclusivo de esa invocación de sombreador.
En otras palabras, como no existe una función o la pila o un montón, todas las variables declaradas en cualquier lugar viven en un registro. Si son locales para algún ámbito en GLSL o globales para todo el archivo, no hay diferencia. Son solo registros.
Sin embargo, el asignador de registros no forma parte del estándar GLSL. Las diferentes implementaciones de OpenGL pueden tener diferentes niveles de calidad cuando se trata de convertir el código GLSL de alto nivel en el código de máquina de bajo nivel que entiende la GPU. Una de las partes más complicadas de un compilador (GLSL o no) es la asignación de registros . Esta es la parte del compilador que determina qué registros ocupa una variable determinada. C lo tiene un poco más difícil ya que generalmente tiene que lidiar con archivos de registro muy pequeños (especialmente en x86) y tiene que lidiar con el derrame de registros (mover variables a la pila) y alias (guardar variables de nuevo en la RAM antes de llamar a las funciones) y instrucciones impares que exigen que la salida esté en un registro particular (x86idiv
por ejemplo). Las GPU tienen un archivo de registro de gran tamaño debido a que no tienen pila ni montón, por lo que el asignador puede ser más simple.
Sin embargo, el archivo de registro no es infinito. Si tiene más variables que registros compatibles con su hardware, el compilador tendrá que intentar ajustar todas sus variables en los registros. Esto generalmente requiere alguna forma de verificación del rango de vida . Es decir, si usa una variable xn
para un cálculo y nunca la usa nuevamente, el compilador puede determinar esto y luego saber que el registro ocupado por xn
podría ser usado por otra variable más adelante, permitiendo así más variables de las que hay registros (siempre ya que no hay demasiadas variables vivas a la vez).
Sin embargo, el compilador podría no hacer esto. No tiene O podría hacerlo solo en algunos casos. Los ámbitos dados a los compiladores más simples son un problema mucho más fácil de resolver. Todos los registros asignados a las variables de función local pueden reutilizarse después de que esa función salga porque sabe que las variables están muertas. Las variables globales no tienen una garantía tan fácil. Por lo tanto, algunos compiladores menos capaces también pueden no optimizar sus vidas, y las variables globales siempre consumirán un registro. Esto no hará que nada sea más lento, pero en algunos controladores puede limitar el tamaño del sombreador que puede escribir.
En general, recomendaría mantener localizadas todas las variables. Mantenga la definición tan cerca del uso de la variable como tenga sentido. Esto se aplica a todos los lenguajes de programación, no solo a GLSL. También recomendaría hacer cada constante "variable" en todos los casos posibles. Una vez más, puede ser una pista para ciertos compiladores menos capaces de que ciertas optimizaciones son posibles y, lo que es más importante, hace que su código sea más autodocumentado y fácil de mantener.
Y, por supuesto, aquí tienes tu obligatorio "solo perfil para probar y averiguar con seguridad". Escriba su sombreador con y sin sus globales y perfílelo. Se debe desconfiar de todos y cada uno de los consejos de rendimiento en línea y se debe suponer que están impregnados o no actualizados.
main()
función? ¿Sus valores son realmente variables globales (uniformes o atributos en lenguaje GLSL) o valores constantes?