miércoles, 3 de septiembre de 2014

LA HISTORIA DEL OPENGL Y EL DIRECT 3D

Jugador de videojuegos detente. Tal vez tu naciste a tiempo para jugar, en los tiempos del HL1. Del quake 1. Del unreal. 
Quizas recuerdes... que antes de, pixel shader, de las gafas 3d, del oculus rift, y del monopolio imperante del directx sobre todas las cosas...habia una epoca. Una epoca en la que si te ibas a las opciones graficas, de alguno de los juegos anteriormente citados, habia una opcion llamada "render device", que te daba a elegir entre: software, opengl o direct3d... Y tal vez, eras tu uno de esos, que sorprendiendote de lo bien que se ejecutaban los juegos en opengl con tu nueva tarjeta 3dfx voodoo2 recien comprada, marcabas siempre esa opcion, preguntandote, porque unos años mas tarde desaparecía, para hacer obligatorio el uso del directx (cuyo rendimiento iba tan lento como siempre).

Adentrate conmigo en esta respuesta que he encontrado en un foro, repasando la historia de, en otra epoca, una vez poderosa libreria grafica, y que me ha impresionado tanto, que he tenido a bien tomarme la molestia de traducir. 
De seguro aprendes algo, sobre el estado actual de la industra, y de por que ahora mismo las nuevas APIS gráficas (opengl 5.0, directx12) se estan reescribiendo partiendo de cero, intentando aprender del sorprendente nuevo jugador en la industria: La api gráfica mantle, de AMD



Esto es una traducción libre, de la brillante respuesta que da un usuario en este foro:
Algunas partes contienen fallos ortográficos.

http://programmers.stackexchange.com/questions/60544/why-do-game-developers-prefer-windows

Un usuario preguntó: ¿Por qué hay tanta predilección de hacer los juegos en directx, por encima de opengl¿Es directx tan superior, o tan facil de programar en comparación con la otra api?

Un usuario respondió:



Muchas de las respuestas que hay aquí son realmente, realmente buenas. Pero el asunto del opengl y el direct3d(d3d) es algo que probablemente debería ser abordado. Y eso requiere...
una lección de historia.


Y antes de que empecemos, conozco mucho más de opengl que de Direct3d. No he escrito nunca ni una sola linea de codigod3d en mi vida, y he escrito tutoriales de Opengl. Así que lo que voy a decir no es un asunto de parcialidad. Es un simple asunto de historia.

NACIMIENTO DEL CONFLICTO.

Un dia, en algún momento a principios de los 90, Microsoft miró alrededor. Vieron a la SNES y a la MegaDrive siendo cojonudas, teniendo tela de juegos de acción y eso. Y vieron el DOS. Los desarrolladores escribían el codigo de juegos para dos, como para consolas: Directo en el metal. A diferencia de las consolas, sin embargo, donde el desarrollador que hacía un juego para SNES lo hacía sabiendo que hardware iba a tener, los desarrolladores de DOS tenían que escribir para multiples posibles configuraciones. Y esto es algo bastante mas duro de lo que parece.

Y Microsoft tenía un problema más grande: Windows. Verás, Windows quería dominar el hardware de una forma bastante diferente a la forma en la que DOS les permite hacer cualquier cosa.
Dominar el hardware es necesario para tener cooperacion entre aplicaciones. La cooperacion es exactamente lo que los desarrolladores de juegos odian, porque coge todos los preciosos recursos de hardware, que ellos podrían estar usando para ser la fantásticos.*1 




Para promocionar el desarrollo de juegos en Windows, Microsoft necesitaba una API uniforme que fuera de bajo nivel, corriera bajo windows sin ser demasiado ralentizada, y por encima de todo multiplataforma. Una sola API para los graficos, el sonido y la entrada de hardware.

De esta forma, Directx nació.

Las (tarjetas gráficas) aceleradoras 3d nacieron unos meses más tarde. Y Microsoft tuvo un pequeño problema. Veras, DirectDrwaw, el componente gráfico de Direct, solo trataba con gráficos 2d: alojando la memoria en pedazos de bits, en diferentes secciones de la memoria.

Asi que Microsoft compró unos sofwares intermedios y lo vistió como Direct3d versión 3. Esto fue universalmente vilipendiado. Y con razón: mirar código de D3d v3, es como echar un vistazo al Arca de la Alianza.

El viejo John Carmack en Id Software le dio un vistazo a esa basura y dijo, "Que se joda eso!", y se puso a escribir otra API: OpenGl.

Verás, otra parte de esa enorme bestia de varias cabezas que es Microsoft, había estado ocupada con Sillicon Graphics, en la implementación de Opengl para windows. La idea era cortejar a diferentes desarrolladores de aplicaciones GL típicas, las aplicaciones de las estaciones de trabajo. CAD tools, modelado...esa clase de cosas. Los juegos eran la cosa más impensable que tenían. Esto fue más por una cosa del windows NT, pero Microsoft decidio añadirselo después tambien al win95.

Como una forma de atraer desarrolladores de estaciones de trabajo a Windows, Microsoft decidió tentarlos con acceso a esas nuevas flamantes tarjetas 3d. Microsoft implemento el protocolo de Drivers instalable: Un fabricante de tarjetas gráficas podría sobreescribir el software de Microsoft para Opengl, con el hardware de uno. El código podría automáticamente usar el hardware de Opengl que estuviera disponible.

En los primeros dias, las tarjetas de nivel de usuario, no tenían soporte para Opengl. Eso no detuvo a John Carmack, de hacer un port de Quake a OpenGL (GLQuake), en su estación de trabajo SGI (Silicon Graphics I?). Así, como podemos leer en el readme de GLQuake:


"...Teóricamente, glquake correrá en Opengl compatible que soporte extensión de textura de objetos, pero a menos que sea un hardware muy potente que acelere todo lo necesario, el juego no se ejecutará aceptablemente. Si tiene que ir a traves de un camino de emulación de software, el rendimiento irá sobre un frame por segundo.

Por esta época (marzo del 97), el único estandar de hardware opengl que podía manejar glquake razonablemente, es intergraph realiz, que es una tarjeta TELA DE CARA: 3dlabs ha estado mejorando su rendimiento significativamente, pero con los drivers disponibles, (sus tarjetas) no eran todavía lo bastante buenas como para usarse. Algunos de los actuales drives de 3dlabs para placas glint y permedia, pueden incluso crashear NT, cuando salen del modo pantalla completa, así que no puedo recomendar su uso.

3dfx ha provisto un opengl32.dll que da todo lo que glquake necesita, pero NO es una implementación completa de opengl. Otras aplicaciones de opengl, no van a trabajar bien con esto, así que lo considero simplemente un "driver de glquake"....".


Este fue el naciemiento de los miniGL drivers. Acabaron evolucionando hacia implementaciones completas de openGL eventualemente,  así como el hardware se volvía cada vez más potente para implementar todas las funcionalidades de Opengl. Nvidia fue la primera en ofrecer una implementación de Opengl completa. Muchos otros vendedores lucharon, lo que es una razón de por qué los desarrolladores prefirieron el Direct3d: eran compatibles un rango más grande de software. Eventualmente, solo nvidia y ati (ahora amd) quedaron, las dos con una buena implementación de opengl.



LA ASCENDENCIA DEL OPENGL.

Así, la contienda está servida: Direct3d vs Opengl. Es realmente una historía apabullante, considerando cuán malo D3d v3 era.


La comisión para la revisión de la arquitectura Opengl (el ARB) es la organización responsable del mantenimiento del Opengl. Ellos llevan un número de extensiones, manteniendo el repositorio de extensiones, y crean nuevas versiones. El ARB es un comite formado por muchos de los grandes jugadores de la industria, así como de fabricantes de sistemas operativos. Apple y Microsoft han sido varias veces miembros del ARB.

3dfx va y saca la Voodoo2. Esta es la primera tarjeta que puede hacer multitextura, que es algo que el Opengl no podía hacer antes. Mientras que 3dfx esta fuertemente en contra del Opengl, Nvida, hacedores del primer chip gráfico de multitexturado (el TNT1), lo ama. Asi que el ARB añadió de una extensión: GL_ARB_multitexture, que podría permitir el acceso al multitexturado.

Mientras tanto, el Direct3d v5 sale. Ahora d3d, tiene una auténtica API mejor que algo que parece que lo ha vomitado un gato. El problema? No tiene multitexturado.

Oops.

Ahora, esa no dolió tanto como hubiera debido, porque la gente no usaba el multitexrurado mucho. No directamente. El multitexturado dañaba el rendimiento un poco, y en muchos casos, no valía tanto la pena, comparado con el multi-pasado. Y, por supuesto, los desarrolladores de juegos amarían que sus juegos siguieran funcionando en tarjetas más antiguas, que no tenían multitexturado, asi que muchos juegos vinieron sin él.

Al d3d, se le dio pues, un indulto.

El tiempo pasa, y Nvidia saca la Geforce 256 (lo la GT-250, la primera geforce de verdad), cargándose la competición de tarjetas gráficas durante los dos años siguientes. El principal aliciente de sus ventas fue la transformación e iluminación de vértices en el hardware. (T&L). No solo eso, Nvidia amaba tanto al opengl, que su motor de T&L era efectivamente un motor Opengl. Casi literalmente; así como yo lo veo, algunos de sus registros cogieron enumeradores en valores de Opengl directamente.

Direct3d v6 sale. Multitextura al final, pero... no hay hardware para T&L. Opengl siempre tuvo una producción de T&L, incluso antes de que la 256 la implementara en software. Así que fue muy fácil para Nvidia, simplemente convertir la implementacion de su software a una solución de hardware. No fue hasta el D3d v7, hasta que D3d, tuvo soporte para T&L.




EL AMANECER DE LOS SHADERS, EL CREPÚSCULO DEL OPENGL

Entonces, la Geforce 3 salio. Y un montón de cosas pasaron a la vez.

Microsoft había decidido que no iban a llegar tarde otra vez. Así que en vez de ver que iba a hacer Nvidia, y copiarles después, hicieron la increble jugada mandar a alguien a a sus oficinas a hablar con ellos. Casi inmediatamente de haberse conocido, las dos compañias se enamoraron, y el fruto de la relación fue que tuvieron una pequeña consola juntos.

Más tarde llegaría el divorcio, pero eso es otra historia.

Lo que esto significaba para el PC fue que la Geforce 3 salio casi simultáneamente al D3dv8. Y no es difícil ver como la Geforce 3 influenció los shaders de d3d 8. El Shader model 1.0, era extremadamente específico para las tarjetas de nvidia. Apenas habia que hacer ningún esfuerzo para abstraer el hardware de la tarjeta. El sm 1.0 hacía exactamente lo mismo que la tarjeta.

Cuando ATI empezó a meterse en el tema de los gráficos 3d con la radeon 8500, había un problema. El procesado de pixeles en la 8500 era más poderoso que en las de Nvidia. Así que Microsoft creó el shader model 1.1, para hacer básicamente "todo lo que la 8500 hacía.

Eso puede sonar como una cagada por la parte del d3d, pero cagada y éxito son un tema de centimetros. Un fallo épico estaba pasando en opengl-landia.


Nvidia amaba el opengl, asi que cuando la geforce 3 salio, ellos sacaron extensiones de opengl. Extensiones de opengl propietarias: solo funcionaban con nvidia. Naturalmente, cuando la 8500 salio, no podia usar ninguna de ellas.

Mira, al menos en d3d 8-landia, podias correr el shader model 1.0 en las tarjetas de ati. Oh si, claro, tenias que escribir nuevos shaders para aprovecharte de las wapadas de la 8500, pero al menos, tu codigo funcionaba. (nota del traductor, no importan los goles anteriores, esto es atrapar la bola dorada del quidditch)

Para poder tener shaders de alguna clase en la radeon 8500 en opengl, ati tenia que escribir, una serie de extensiones en opengl. Extensiones propietarias: Solo para ATI. Asi que necesitabas un camino de codigo de nvidia a ati, solo para tener shaders.

Ahora te preguntaras "Que coño estaba haciendo el comite opengl ARB, cuyo trabajo es mantener el OPengl moderno, y con shaders? Pues estaban haciendo lo que suelen hacer la mayoria de los comites: ser idiotas.

Veras, he mencionado el ARB_multitextura arriba, porque es una clave muy profunda en este asunto. El ARB parecia (desde la perspectiva de un tio que lo mira desde fuera), que estaban boicotenado el tema de los shaders totalmente.Ellos creian que si cambiaban la configuracion en el desarrollo de funciones lo bastante, podrian sacar equivalentes a los shaders.

Asi, el ARB fue sacando extension tras extension. Cada extension con las palabras "texture_env", en una serie de intentos de ir parcheando el diseño antiguo. Mira los registros: entre el ARB y el EXT hay hechas ocho versiones. Muchas de ellas promocionadas como versiones del nucleo de opengl.

Microsoft era parte del ARB en aquellos momentos, se largaron en la epoca en la que pegó el d3d 9. Asi que es perfectamente posible que estuvieran en el comite, pensando en sabotear el opengl de alguna forma. Pero yo dudo esta teoria por dos motivos: Uno, tendrian que haber tenido ayuda de mas de un miembro de ARB, ya que cada miembro solo tiene un voto. Y mas importante, dos: el ARB no necesitaba la ayuda de microsoft para joderlo todo, como se probará mas adelante.

Eventualmente el ARB, como si estuvieran amenazados por ATI y Nvidia (ambos miembros activos), sacaron la cabeza lo bastante como para implementar shaders de estilo de ensamble.

¿Quieres algo mas estupido?

El T&L por hardware, algo que el Opengl tuvo primero, para tener el máximo rendimiento posible por hardware, necesitas almacenar datos de vertices en la GPU. Despues de todo, es la GPU la que actualemtne quiere usar esos datos de verticies.

En D3d, v7, Microsoft introdujo el concepto de los vertices buffer. Eran andanas localizadas en la memoria de la gpu para almacenar datos de vertices.

Quieres saber cuando opengl tuvo su equivalente de esto? Oh, nvidia, siendo amante de todas las cosas Opengl (tanto como para hacer extensiones propietarias, solo para nvidia), solto un rango de extensiones con su primera hornada de geforces 256. Pero, ¿cuando el ARB penso en dar una funcionalidad similar?

Dos años mas tarde. Despues de esto, aprobaron shaders de vertices y fragmentos (pixeles en lenguaje d3d). Eso es el tiempo que le llevo a ARB desarrollar una solucion multiplataforma para almacenar datos en la memoria de la GPU. De nuevo, algo que el hardware de T&L, necesita para llegar a su maxima potencia.


UN LENGUAJE PARA ARRUINARLOS A TODOS.


Asi, el desarrollo del entorno del opengl estuvo fracturado por un tiempo. No hubo shaders multiplataforma. No hubo almacenamiento de vertices en la gpu, mientras que los usuarios del D3d, disfrutaban de ambos. ¿Podria ponerse peor?


Claro que si. Aqui llega 3d labs.

Quienes son, podrias preguntarte? Son la difunta empresa que yo considero que fue la autentica asesina del opengl. Seguro, la ineptitud general del ARB hizo al Opengl vulnerable cuando deberia haber estado destruyendo al d3d. Pero 3d Labs es quiza, la mayor unica razon que me llega a la mente, del estado del opengl en el mercado. Que podria haber hecho para provocar eso?

Ellos diseñaron el lenguaje de shaders de opengl.

Veras, 3d labs era una compañia agonizante. Sus super caras tarjetas graficas, fueron marginadas con la creciente presion de nvidia en el mercado de las estaciones de trabajo. Y, a diferencia de nvidia, 3d labs no tenia tarjetas en el mercado de usuarios normales. Si nvidia ganaba, ellos morian.

Y eso hicieron.

Asi, en un ultimo esfuerzo por permanecer relevantes en un mundo que no querian sus productos, 3d labs enseñaron en una conferencia de desarrolladores de juegos, algo que llamaron "opengl 2.0". Esto era un completo reinicio, partiendo de cero, de la API opengl. Y tenia sentido. Habia un monton de mierda en la api de opengl, en aquel momento (nota, esa mierda todavia persiste). Solo mira como fundiona la carga de texturas: es semiarcano.

Parte de la propuesta era un lenguaje de shaders. Naturalmente. Sin embargo, a diferencia de las extensiones multiplataforma ARB, su lenguaje para shaders era de alto nivel (C es un lenguaje de alto nivel para shaders. Si, de verdad).

En aquel entonces, microsoft tambien se encontraba trabajando en su propio lenguaje de alto nivel, el cual llamaron, en un esfuerzo de imaginacion colectiva... el "lenguaje de shaders de alto nivel". Sin embargo, su aproximacion era muy diferente al resto.

El mayor problema con el lenguaje de shaders de 3d labs, era que estaba integrado. Mira, el de microsoft estaba muy definido. Le crearon un compilador. Le generaron el shader model 2.0, le dieron codigo de ensamblador, con el que podias alimentar d3d. En los dias del d3d v9, el lenguage de microsoft (hlsl), nunca tocaba d3d directamente. Era una bonita abstraccion, pero puramente complementaria. Y el desarrollador tenia la poportunidad de ir detras del compilador y ajustar la salida, para tener el maximo rendimiento.

El lenguaje de 3d labs no tenia nada de eso. Tu le dabas al driver un lenguaje como el C, y producia un shader. Fin del asunto. NI un shader de ensamblador, ni tenias que alimentar nada mas. Era el objeto en opengl, representando el shader.

Lo que esto significa es que los usuarios de opengl fueron objeto de las vagancias de los desarrolladores que simplemente estaban manejando lenguajes sin ensamblar. Los bugs galopaban por doquier en el lenguaje de shaders opengl (GLSL). Lo que era peor. Si conseguias tener un shader que compilaba en multiples plataformas (una hazaña), todavia estabas sujeto a las optimizaciones de ese dia. Lo que no era algo tan optimo como podia ser.

Esto era el peor fallo del GLSL, pero no el unico. Ni de lejos.

En d3d, y en los lenguajes de ensamblado de opengl, podias mezclar y encajar vertices de pixel shaders. Siempre y cuando se comunicaran con el mismo interface, podias usar cada shader con cualquier otro fragmento de shader compatible. E incluso, habia niveles de incompatibilidad que se podian aceptar. Un vertex shader podia producir una salida, que el fragmento de otro shader no leyera, y asi sucesivamente.


GLSL no tenia nada de eso. Los vertices y fragmentos de shaders se fusionaban juntos en los que 3d lab llamaba "un programa objeto". Asi que si querias compartir vertices y programas objetos, tenias que construir multiples programas objeto. Y esto causo el mayor segundo problema.

Veras, en 3d labs pensaron que estaban siendo listos. Basaron su compilacion de GLSL en c/c++. Si tu coges un .c, o un .cpp, y lo compilas en un archivo objeto. Y entonces coges uno o mas objetos y los enlazas en un programa. Asi es como el GLSL compila: tienes que compilar tu shader (vertice o fragmento) en un objeto shader. Entonces pones esos objetos shaders en un programa objeto, y los enlazas juntos para hacer el programa entero.

Mientras que esto permite un monton de potenciales ideas molonas, como tener una "libreria" de shaders que contiene codigo extra que los shaders principales podrian llamar, lo que lleva a la practica es que los shaders tienen que compilarse dos veces. Una en la fase de la compilacion, y otra en la fase del enlazado. El compilador de nvida en particular era conocido por tener  la compilacion doble. No generaba ninguna clase de objeto codigo intermediario. Solo compilaba una vez, lanzaba la respuesta y entonces compilaba una segunda vez en el tiempo de enlazado.


Asi, incluso si quieres enlazar tu shader a dos fragmentos de shaders, tienes que hacer un monton mas de compilacion que en d3d. Especialmente desde que compilar en un lenguaje tipo C, se hacia todo offline, no al principio del la ejecucion de programa.

Hay otros asuntos con el GLSL. Quiza parece equivocado echar toda la culpa a 3d labs, ya que el ARB eventualmente, aprobo e incorporo este lenguaje (pero nada mas de su iniciativa "opengl 2.0"). Pero fue idea de ellos.


Y ahora viene la parte realmente triste: 3d labs estaba en lo cierto (en la mayoria de todo). GLSL no es un lenguaje de vectores basado en shaders de la forma que el HLSL lo era. Esto fue porque el hardware de 3d labs era escalar (parecido al de nvidia), pero estaban en lo cierto en la direccion en la que los fabricantes de hardwares acabaron yendo.

Estaban en lo cierto en lo de compilar online para el nivel alto del lengual. D3d nunca llego a mirar a eso siquiera.
El problema es que 3d Labs estaban en lo cierto, en el momento equivocado, e intentaron llegar al futuro demasiado pronto. Cuando uno intenta hacer soluciones demasiado enfocadas a como sera en el futuro, se la pegan en el presente. Suena simiar a como el opengl siempre ha tenido la posibilidad de hacer T&L desde un primer momento, pero no fue exitoso hasta que habia hardware T&L, mientras que el GLSL estuvo disponible antes de que el mundo lo pillara.

El GLSL es un buen lenguaje ahora. Pero, en su epoca? Era horrible. Y opengl sufrio por eso.


DE LA CAIDA A LA APOTEOSIS.


MIentras que yo mantengo que 3d Labs dio el golpe fatal, fue el ARB mismo quien seria el que clavaria el ultimo clavo del ataud.

Esta es una historia que muchos de vosotros habreis oido. Es de los tiempos en los que el opengl2.1 estaba teniendo problemas. Tenia un monton de mierda en su legado. La API ya no era facil de usar. Habia 5 formas de hacer una misma cosa, y nadie estaba seguro de cual era la mas rapida. Podias "aprender" opengl, con tutoriales simples, pero aprender esa api para que te diera autentico rendimiento, y poder grafico no era posible.

Asi que el ARB decidio intentar otra reinvencion del opengl. Esto iba a ser parecido a lo que 3dlabs hizo con el opengl 2.0, pero mejor porque ARB estaba detras de ello. 
Lo llamaron el salto largo. (Longs peak).

Que es lo que tiene de malo el que te lleve tanto tiempo mejorar una api? Esto era malo porque en microsoft se habian dejado ellos solos vulnerables. Veras, esta fue la epoca del naciemiento del windows vista.

Con vista, microsoft habia decidido llevar a cabo muchos cambios muy necesarios en los drivers de pantalla. Ellos forzaron a los drivers a enviar hacia el sistema operativo la memoria grafica de virtualizacion y muchas otras cosas. Mientras que uno puede debatir los meritos de esto, o si es algo que valga la pena, el echo que queda es esto: microsoft forzo a d3d 10, que fuera solo para vista (y versiones superiores)

Si tu tenias una tarjeta, que podia manejar d3d10, no podias usarla, sin tener que tener tambien windows vista.

Quiza recuerdes tambien que Vista...em, bueno, vamos a decir que no funcionaba todo lo bien que debia. Asi que tenias un sistema operativo que no rendia bien, una nueva api, que solo se ejecutaba en ese sistema operativo, y una generacion de hardware fresco que necesitaba esa API y ese os, para no hacer nada que ser mas rapido que la generacion pasada.

Sin emabargo, los desarrolladores podrian acceder a funciones de d3d 10 por opengl...o, bueno... habrian podido, si el ARB no hubiera estado ocupada trabajando en uno de los saltos largos.


Basicamente, el ARB tardo de un buen año y medio a dos años en mejorar la api. Por la epoca en la que el opengl 3.0 salio, la adopcion de vista ya estaba mas al alza, win7 estaba a la vuelta de la esquina, y la mayoria de los desarrolladores de juegos no se preocupaban por las caracteristicas de d3d 10. Despues de todo, las tarjetas graficas que ejecutaban d3d 10, tambien ejecutaban el d3d v9 perfectamente, y con el nacimiento de los ports de pc a consola, ( o los desarrolladores de juegos saltando al desarrollo de consolas, coja su ticket), simplemente los desarrolladores no necesitaban las caracteristicas de d3d 10.

Ahora, si los desarrolladores tienen acceso a esas caracteristicas via opengl o maquinas winxp, entonces el desarrollao de opengl podria haber recibidon un bien merecido tiro en el brazo. Pero el arb perdio su oportunidad. Y quieres saber cual es la peor parte?

A pesar de haber perdido 2 preciosos años intentando reconstruir la api desde cero...todavia hab fallado intentando volver a su estatus quo (excepto por el mecanismo de desprestigio).
Asi que no solo el ARB ha perdido una oportunidad crucial, ellos ni siquiera han hecho la tarea de tener esa oportunidad para poder perderla. Un fallo epico.

Y esa es la historia del openglo vs direct3d. Un cuento de oportunidades perdidas, estupidez bruta, ceguera total, y simple tonteria.

===============================================================


*1. Las repercusiones de este enfoque se pueden ver en la más rotunda actualiadad. Open gl5, mantle y directx12, se van a reescribir, para dar acceso directo de los juegos a los recursos del sistema.

No hay comentarios:

Publicar un comentario