jueves, 25 de julio de 2019

¿Será Vulkan un "reemplazo" para OpenGL?

Abrir una ventana y dibujar un triangulo. Uno feo, uno cualquiera, liso o vacío, da igual. ¿Cuán complicado puede ser? En C o C++, con GLUT y OpenGL 1.x, me van unas 40 lineas de código. Parece mucho para un simple triangulito, ¿no? Creo que en Basic me llevaba 4 instrucciones... y mi primera tortuga lo hacía en 6.

Pues verán que no es tanto cuando les cuente que con GLFW + OpenGL 3.x me llevó casi 200 lineas (y sin contar los shaders)... Pero eso tampoco es tanto: Con Vulkan pasé las 900 antes de dar a luz al 1er triángulo... ¿Es Vulkan una API terrible?


Mi respuesta es que no, tal vez todo lo contrario. Para los que no la conocen, Vulkan es la API que ha venido a "reemplazar" a OpenGL. Pero pongo "reemplazar" entre comillas porque en algún sentido es cierto, y en otro es muy muy falso.

Hola mundo gráfico:  Col 1: OpenGL 1.x - Col 2: OpenGL 3.x; Cols 3 y 4: Vulkan 1.x

¿Por qué sí? Porque para los grandes estudios de Juegos o aplicaciones gráficas (diseño, simulación, etc) donde se requiere alto realismo o alto rendimiento, OpenGL tenía sus problemas, y creo que Vulkan va a solucionarlos. Los fabricantes de GPUs tiran para el mismo lado, quieren ver sus placas al máximo. ¿Por qué no? Porque son cosas muy distintas. Por ejemplo, yo no quisiera tener que implementar el editor de diagramas de PSeInt sobre Vulkan, o perder 3 semanas de clases explicando todo eso para que recién después puedan empezar a hacer la práctica que sí me interesa.


El problema principal está en el nivel de abstracción. OpenGL (por motivos históricos si se quiere) apunta a un nivel de abstracción muy alto como para sacarle todo el jugo al hyper-complejo hardware actual. Hay cierta distancia entre las ordenes de (comparativamente) alto nivel que solemos dar desde OpenGL hasta lo que realmente ocurre en la GPU. Y como toda "bajada" de nivel (compilación), hay muchos caminos.

El que hace la placa intenta adivinar qué va a hacer el programador del otro lado para priorizar (en el driver) el camino óptimo según ese caso de uso. Del otro lado, el que hace el juego, intenta adivinar qué camino tomará el driver para tratar de solo pedirle las cosas que serán realmente eficientes (no las que cree que tomaran un camino largo). Pero hay muchas placas, y muchos juegos, mucho que adivinar. Solo en algunos casos de estudios AAA y empresas como NVidia, suele pasar que el ingeniero de la GPU y el programador del motor de juego se ayudan entre sí. En la mayoría de los casos no está esa posibilidad, y eso es un gran problema.

Entonces, es natural buscar una API de más bajo nivel, que deje menos lugar al "tener que andar adivinando" y haga todo más explícito, que ceda más control (y más responsabilidad). Por eso Vulkan es otra cosa, porque está en otro nivel de abstracción. Y eso lo hace tan verborrágico, hay que andar diciendo y previendo absolutamente todo. Cuando menos te das cuenta, van 600 lineas de boiler-plate-code y todavía no está el 1er pixel en la ventana. Y por eso OpenGl seguirá vivo, tal vez hasta que algún wrapper sobre Vulkan se convierta en el nuevo estándar de facto.

Una slide de una presentación oficial del grupo Khronos

Pero hay [muchos] más aspectos en los que Vulkan cambió/acentuó el enfoque, veamos uno en particular. Tomemos como ejemplo un simulador. Allí puede ser vital la diferencia entre tardar 15ms o 20ms para renderizar un frame. Eso se traduce en más FPSs y/o más realismo. Y todos coincideremos en que es mejor tardar 5 segundos más en cargar si a cambio mejora la experiencia "durante" el juego. Es decir, precalcular de ante mano todo lo que se pueda, total va una sola vez. Vulkan hace eso con el pipeline gráfico.

Hace años que el pipeline no es fijo. Aún para un solo frame, se suelen hacer varias pasadas sobre partes de la escena con diferentes configuraciones. Vulkan está pensado para que antes de empezar a jugar, le digamos tooooodo lo que vamos a necesitar, para tooodas las configuraciones que podamos llegar a usar. Entonces, en lugar de cambiar detalles de configuración "durante" la generación de un frame, con Vulkan armamos antes de empezar "varios pipelines" diferentes, y en cada pasada utilizamos uno ya listo (y además, ya pre-optimizado con tiempo por el driver de video, aprovechando que ahora sí sabe todos los detalles de lo que va a pasar).
En mi notebook (i3 7ma gen, video Intel HD 620) una Suzanne de 8e6 quads (más no 
me da la VRAM) y a pantalla completa (1920x1080px) con Vulkan fluye a 30 FPS .

Sí, en código es un viaje detallar toooodo, y varias veces, preparar tanto. Por otro lado, desde que tenemos el 1er triángulito, hasta la mona completa, hay muy poco más que hacer, ya todo estaba precocinado. El trabajo pesado se hace de ante-mano sí o sí, y por eso es tan difícil arrancar. Pero una vez en marcha, la cosa vuela. Es una buena filosofía, cambiar esa curva inicial, por un mejor andar el resto del viaje. No es para todos. No siempre es el mejor compromiso. Pero muchas veces, de eso se trata la ingeniería, de saber elegir y saber hacer los compromisos adecuados para cada problema.

2 comentarios: