La compilación de shaders se ha convertido en una de las desventajas del PC Gaming respecto a las consolas y es que de repente aunque tengas el ordenador para gaming más potente te encuentras con que el juego tiene parones y el rendimiento baja en picado. Se trata de uno de los problemas más comunes en rendimiento a la hora de jugar.
Todos los juegos a día de hoy tienen parte de su código fuente que es ejecutado por la GPU en forma de unos programas a los que denominamos shaders y que se ejecutan en las unidades homónimas del procesador gráfico. El nombre de estas unidades cambia según la marca de la que estemos hablando, así por ejemplo son llamadas SM por NVIDIA, Compute Unit por AMD y Xe Core por parte de Intel. ¿Su función? Ejecutar una serie de programas que hacen uso de la enorme capacidad para el cálculo en paralelo, ya sea para la manipulación de primitivas gráficas como para aplicar algoritmos matemáticos a gran velocidad.
El problema de la compilación de shaders
Las unidades shader difieren en arquitectura de lo que es una CPU convencional y tienen ciertas carencias que les impiden funcionar en el centro de un PC, pero no entraremos sobre esto aquí, pero una cosa que sí que tienen es un set de registro e instrucciones y dado que nadie programa en binario existen lenguajes de alto nivel que los seres humanos podemos utilizar para escribir dichos programas. ¿Los más conocidos en PC? HLSL en DirectX y GLSL en Vulkan y OpenGL.
¿El problema en PC? Los propios fabricantes no respetan su ISA de un diseño de GPU a otra, esto hace que los programas shaders no puedan venir compilados. No hablamos de que el set de registros e instrucciones cambie de una generación a otra, sino que incluso esto puede ocurrir en una misma familia. Esto hace que en los juegos de PC los shaders se tengan que compilar al vuelo y supone una pérdida de rendimiento mientras jugamos.
La compilación de shaders se ha convertido en un problema a la hora de jugar a muchos juegos en PC, en especial en los juegos de mundo abierto de gran tamaño donde los datos se emiten de manera continua a la RAM a medida que vamos explorando el entorno y, por tanto, con pocas paradas para cargar un nuevo nivel, algo que se hará más común con el SSD NVMe. ¿El motivo? Los tiempos de carga en muchos videojuegos para PC se utilizan para compilar shaders.
Esto no ocurre en consolas
Una consola de videojuegos no cambia ni un bit de sus especificaciones en todo su tiempo de vida, lo que significa que su GPU no cambia y en consecuencia tampoco lo hace su ISA. Dicho de otra manera, no es necesaria la compilación de shaders al vuelo como en PC y estos ya vienen compilados junto al resto del código del juego.
Esto es un arma de doble filo, de cara a la compatibilidad hacia atrás de futuros sistemas. Por ejemplo buena parte del desarrollo de las APU de las Xbox Series y PS5 tiene que ver con entender el binario de los shaders de la generación anterior. Al mismo tiempo Nintendo y NVIDIA de cara a la sucesora de Switch tienen que desarrollar una variante que entienda los shaders compilados para la GPU de la consola híbrida.
La solución más lógica al problema
Para solventar el problema de la compilación de shaders en los juegos de PC existen dos soluciones distintas:
- Crear un repositorio al que el juego pueda acceder durante la instalación que tenga el código shader ya compilado para cada ISA de las tarjetas gráficas que sea diferente. El problema es que esto haría que los desarrolladores tuvieran que mantener dicho repositorio creciente durante un largo tiempo sin ningún tipo de compensación económica.
- Realizar la compilación de los shaders durante la instalación del juego, se tarda un poco más, pero el rendimiento del juego queda afectado.
¿Qué es lo que creemos que harán la mayoría de desarrolladores? Utilizar los núcleos de más de las diferentes CPU de Intel y AMD para ejecutar la compilación de shaders con ellos. Se trata de una de las tareas en segundo plano que por ejemplo harán los E-Cores del Intel Core 12, aunque en general se acabarán usando varios núcleos en paralelo para ir compilando lo más rápido posible los diferentes programas shaders, más cuando los tiempos de carga para ello desaparecerán por el uso de unidades de estado sólido de alta velocidad.