Para explicar la GPU del futuro tenemos que hacer un viaje a un pasado reciente con la máquina del tiempo, a 2007 exactamente como punto de partida. En ese año Intel presento pr primera vez una propuesta de una GPU un tanto especial a la que llamaron Project Larrabee.

larrabee-pci

Larrabee empezó en el 2006 como proyecto para ser presentado en 2007. ¿Su naturaleza? Completamente distinta a la de las GPUs (Si, la entrada de antes tenía un proposito) Larrabee no tenía que ser una GPU al uso sino ser un producto consistente en varios núcleos convencionales de CPU, pero con una serie de diferencias importantes respecto a ls CPUs que había por aquel entonces en el mercado.

Larrabee_block_diagram_(Total_pic._and_CPU_core_bloack).PNG

El procesador en su planteamiento inicial consistía en 16 núcleos P54C altamente modificados, el P54C era el primer Intel Pentium que Intel hizo aparecer en 1993 pero en el caso del Larrabee este fue altamente modificado con una serie de cambios que no se encontraban en la CPU original.

  • Soporte para cache de segundo nivel, el P54C como mucho soportaba el primer nivel de cache. No solo eso, sino que se añadio un sistema en que todas las caches eran coherentes entre si.
  • Se cuadriplico la unidad de control para que este pueda operar con 4 hilos de ejecución distintos. Esto no es 4 veces el procesamiento sino pasar de 1 hilo de ejecución a 4. Por aquel entonces la capacidad de cambiar de contexto en una GPU no era obligatoria en los productos comerciales.
  • Se añadio una unidad SIMD de unos 512 bits y por tanto capaz de operar con 16 operandos de 32 bits, lo cual es estandar en las GPUs.
  • Larrabee carecía por completo de unidad de rasterizado, teniendo que realizar dicha función por «software».
  • También carecía de ROPS, escribiendo el resultado final durante el pipeline gráfico en la Cache L2, pero en cambio si que tenía unidad de texturas.

¿La forma de renderizar la escena? Bueno, lo que voy a citar ahora os sonara bastante:

Las GPUS actuales utilizan el sort-last de Elridge. Esto permite a los resultados de los Pixel Shaders ser ordenados en un número de pequeña regiones alineadas con la pantalla justo antes del depth testing y el blending. A menudo estas regiones alineadas con la pantalla se asocian con controladores de memoria individuales para permitir accesos a la memoria más eficientes. Los fragmentos en Sort-Last permiten un modo inmediato de renderizado con búfers FIFO relativamente cortos para orenador los datos. Sin embargo, si un pixel es accedido múltiples veces en intervalos ampliamente separados se tiene que leer y escribir en memoria multiples veces.

Ejem…

sortlast

Sigamos.

Los algoritmos Sort-Middle han sido llamados  binning, tiling, chunking,
bucket, y zone rendering [Hsieh et al. 2001; Chen et al. 1998].

Este proceso procesa los vertices para producir coordenadas de pantalla para las primitivas, las cuales son entonces ordenadas en contenedores basados en su localización en la pantalla. Cada contenedor es asociado con un región tile en la pantalla. De tal manera que puede ser colocado en la cache de dentro del chip de tal manera que solo un acceso a la memoria es necesario independientemente de la complejidad de profundidad (nota de Urian: overdraw). Un  problema es que las primitivas que se encuentran en varios tiles han de ser almacenadas en múltiples compartimientos. Molnar et al. [1994], Chen et al.[1998], y Eldridge [2001] concluyeron que el impacto de la superposicion era pequeño en comparacion con el tamaño de la región, lo cual ocurre cuando la cantidad de triangulos en la escena crece.

Es decir, esto es lo que tradicionalmente llamamos Tile Rendering.

tilebuffer

En el Tile Rendering antes de realizar la rasterización de la escena lo que se hace es ordenar la geometría de la escena en cada tile/compartimiento y se genera una lista de pantalla por cada uno de ellos.

tiletriangle

La geometría ya esta procesada pero se rasteriza cada tile como si fuese el renderizado e una pantalla. En el caso de las PowerVR lo que se hace es crear un espacio de 32×32 pixeles eliminando de cada tile durante el rasterizado los pixeles del fragmento resultante derivado del triangulo que quedan fuera del Tile. Luego se elimina el overdraw porque en una especio muy pequeño es fácil realizar una operación de eliminacion de pixeles no visibles porque el area es muy pequeña. ¿Pero y que hay de los accesos a memoria? Pues simple y llanamente tanto el Z-Buffer como el Color Buffer se almacenan en la cache interna lo que reduce el impacto sobre la memoria.

Intel con el Larrabee buscaba almacenar los Tiles en la Cache L2 y que los núcleos operasen la rasterización y los shaders directamente sobre ellos. Esto era un cambio enorme respecto a los shaders tradicionales y es que el Larrabee tenía el set completo de instrucciones de una CPU y por tanto sus ALUs eran altamente complejas. Los Tile Renderes convencionales operan con los Tiles a nivel de registro pero no hay varios niveles pero es normal dada la naturaleza tipica de las CPUs, Intel en cambio con Larrabee le había dado a los Shaders la capacidad de acceso a la memoria completo de una CPU y por tanto no solo la capacidad de acceder a la cache sino a la memoria principal. ¿Que significaba esto? Ahora sería posible ejecutar un código gráfico más completo… ¿Que os parece por ejemplo poder programar el motor del juego no en OpenGL, no en Direct3D… que tal si lo hacemos en C++?

El mayor defensor de este concepto fue Tim Sweeney, el arquitecto jefe de los Unreal Engine que llego a realizar una presentación llamada «The end of GPU Roadmap» en 2009 cuando Larrabee aún no había sido cancelado.

En ella Sweeney hablaba de las limitaciones de las ALUs para los Shaders:

Sweeney1.PNG

La diapositiva es una entrada de lo que os he hablado en la entrada anterior en general, como apunte, dado que los Shaders no pueden acceder más allá que sus registros no soportan tipos de datos complejos como es una estructura de datos. Pero Sweeney no solo atacaba el tema de los shaders sino toda la GPU en general y en especial las unidades de función fija.

Sweeney2.PNG

Si lo pensáis bien, la prediccion de Sweeney se ha cumplido durante esta generación, los juegos actuales se ven marginalmente mejor que el Crysis de PC y la evolucion visual ha sufrido una desaceleración.

Esto es porque hemos llegado al límite de la eficiencia de lo que es la rasterización que es el método de renderizado utilizado hoy en día. Dicho de otra forma, Sweeney abogaba por la destrucción completa del pipeline tradicional y con ello con la supresión del modelo OpenGL que durante años ha reinado en el sector. Para ello entre varios motivos proponía la solución de Intel en parte, la supresión de las unidades de función fija y tirar de Tile Rendering por Software.

Sweeney3.PNG

La motivación de ello la contare más adelante en esta entrada. Sweeney agobaba con que el futuro tenía que ser con el Larrabee como arquitectura de referencia.

Sweeney4.PNG

¿La gran ventaja de eliminar la función fija? Pues que te cargas el pipeline OpenGL convencional y puedes utilizar otros métodos de renderizado.

graphics-rendering-pipelines-big

El concepto es el mismo que el del Cell Broadband Engine, que podía funcionar en dos modos distintos de manera muy parecida el chip de Sony, Toshiba e IBM.

jobsvsstream

Esto le permitía al Larrabee poder adoptar otras formas de renderizado en teoría como es el Raytracing.

Sweeney5.PNG

Intel apostaba por este método de renderizado y le hacía mucha propaganda, pero el método de renderizado para el que Larrabee parecía ser el procesador ideal era REYES.

 

REYES1.PNG

Render Everything Your Eyes Ever Saw. (Geometria y Shading)

REYES fue creado por el estudio de Lucasfilm que se convertiría tiempo más tarde en Pixar.

Dado que incluso el coste de renderizado en los 80 via Raytracing era muy caro para un estudio pequeño y se conocían ya las limitaciones de la rasterización lo que hicieron fue crear un tipo nuevo de renderizado al que llamaron REYES que era mejor que el rasterizado por el hecho de permitir formas superficies suaves como curvas y estar pensado para el cine al estar pensado para el Motion Blur y el Depth of Field. Al ser un nuevo tipo de técnica de renderizado su pipeline es completemente distinto y en parte es compatible con la rasterización dado que REYES es lo que ocurre con la rasterización cuando sus primitivas acaban en una singularidad muy concreta.

REYESPipeline

La evolución de la Rasterización a REYES es algo que se intuye desde hace un tiempo por un motivo bien simple, el concepto de micropolígono. ¿que es? Pues es un polígono cuyo tamaño es de 1 pixel o de menos de un pixel en pantalla, sigue siendo un polígono pero ha sido reducido al tamaño de un solo pixel y solo esta particularidad rompe el pipeline clásico del tipo OpenGL porque lo hace altamente ineficiente.

La primera etapa de REYES es exactamente igual a la Rasterización, pero con una diferencia, aplica a continuación sobre la escena la subdivisión de primitivas para teselar la escena, esto es algo que esta en las GPUs desde DirectX 11 pero con un problema no es teselación adaptativa lo que se hace por hardware y es que todas las GPUs tienen una unidad de función fija que es un teselador que aplica la versión más simple de la teselación que es la Catmull-Clark. Que por cierto también fue inventada en Pixar y por quien ahora es su presidente de animación, Ed Catmull. Pero el problema dee este tipo de renderizado si lo aplicasemos a tiempo real acabaría por producir sobre-teselación en objetos lejanos e infra-teselación en objetos cercanos y sería una perdida de rendimiento enorme.

Muchos juegos contemporaneos hacen servir la teselación adaptativa..

Pero en algunos casos la mejora no resulta en nada en lo que a la calidad de imagen se refiere porque no es posible llegar a la singularidad que es el micropolígono. ¿El motivo de ello? La forma en que las GPUs contemporaneas texturizan aunque eso lo tratare más adelante, vayamos por orden. A medida que ha ido pasando el tiempo se han ido haciendo más y más pequeños los polígonos que componen una escena a tiempo real y es por ello que existe el tema que llegarán a ser lo suficientemente pequeños como para subvertir el pipeline clásico de rasterización.

GeometryEvolution.PNG

¿El motivo de ello? El motivo por el cual los Pixel Shaders son llamados Fragment Shaders es que las unidades de texturas funcionan con bloque de 2×2 pixeles. ¿El motivo?

  • Para realizar el filtro bilineal se necesitan bloques de 2×2 pixeles.
  • Los vertices están compuestos por 4 componentes (X,Y,Z,W) lo que no significa cuatro dimensiones pero el caso es que es mucho más fácil de unificar los shaders en este caso.

¿Y que problema existe entonces? Dado que Pixel/Fragment Shaders están pensandos para funcionar en bloques de 2×2 pixeles por lo menos por el hecho que es como funcionan las unidades de texturas, en bloques de 2×2, por lo que si tenemos 1 micropolígono compuesto por 1 solo pixel lo procesara como si fuesen 4 pixeles por lo que existe es una redundancia enorme y si esta trabajand con micropolígonos de 1/2 pixel entonces ya la ineficiencia es de 8X.

ShadingMicropolygons.PNG

¿Entonces? Aquí es donde entramos en la singularidad porque los vertices acaban siendo tan pequeños que la diferencia entre un vertice y un pixel se difumina por completo y si miramos el pipeline actual de los derivados de OpenGL veremos que existe una etapa de Shaders como mínimo antes del rasterizado, los llamados Vertex Shaders… ¿Que ocurre en REYES? Pues que el concepto es el de «texturizar» antes de la rasterización y no después de la rasterización pero nos encontramos con una particularidad, los micropolígonos son demasiado pequeños como para aplicarles una textura (u,v)

texture

Por lo que la texturización clásica en OpenGL desaparece por completo… ¿Como definimos el valor de cada pixel? Pues a través de los «Shaders» pero hay que tener en cuenta que los nuevos Shaders no son ya ni Vertex ni Pixel que acaban trabajando con 4 componentes distintos sino que trabajan más con un elemento por lo que acabarían siendo más del estilo de los Compute Shaders.

Y aquí entramos en otra de las cosas que la Rasterización le tomo prestado a REYES, los Shaders. A la gente le sorprenderá, pero el concepto de Shaders lo inventa Rob Cook y deriva de su Shade Tree.

ShaderTree

Es más, fue Cook quien invento REYES. Lo que se hizo con el paso de los años es añadir el concepto de manera limitada al pipeline del OpenGL y de ahí nacieron los Shaders modernos. El concepto vendría a ser que cada uno de los micropolígonos no tendría una textura asignada sino un programa shader que definiría por completo su comportamiento, pero en este caso y al contrario que ocurre con OpenGL no utilizaríamos texturas pre-cocinadas para realizar las operaciones.

SetTextureGraph

Sino que dichas texturas serían valores matemáticos directos. ¿Y como podemos definirlos de antemano? Pues por el hecho que es posible darle a un vector un color de base tanto en REYES como en OpenGL por lo que realmente los modelos partirían de ese valor de color base y a partir del mismo operarían.

Bajo este paradigma las unidades de texturas desaparecen por completo del hardware porque ya no son necesarias en ningún momento. La diferenciación entre los tipos de shaders básicos como son el Vertex y el Pixel Shader desaparecen tambíén.  Pero nos queda una última etapa que es el Rasterizado.

Rasterizado en REYES

En OpenGL el Rasterizado es previo a la texturizacion y ambos son previos a la generación de búfer de imagen.

Graphics3D_Rasterization

Lo que genera un rasterizador tipo OpenGL de hoy en día son fragmentos de 8×8 pixeles que son subdivididos en fragmentos de 2×2 pixeles para ser enviados a los shaders. Pero en REYES nos encontramos con que cada micropolígono requiere ser rasterizado y lo es pero… ¿Como se rasteriza? Exactamente igual solo que en una superficie de 1×1 pixel… ¿Y que ocurre con los micropoligonos en el mismo pixel? Aquí es cuando tenemos que entrar en un concepto llamado A-Buffer. ¿Con que situación nos encontramos?

  1. Dado que hemos realizado antes el Shading nos encontramos que cada micropolígono tiene un valor RGBA y por tanto tiene un nivel de transparencia asociado y es mucho más fácil descartar polígonos no-visibles y poder representar adecuadamente los niveles de transparencia sucesivos. Esto se hace almacenando en el A-Buffer no solo un pixel por posición sino una lista enlazada de de ellos que va de adelante hacía atrás.
  2. Como es obvió no hay separación entre Z-Buffer y Color Buffer por lo que tenemos un solo búfer de imagen y no 2 en que cada pixel almacena la lista enlazada de pixeles comentada en el punto 1.
  3. Dado que cada pixel en el A-Buffer almacena varios componentes funciona como un búfer de acumulación en OpenGL.

Con el punto 3 entramos en otra de las cosas que OpenGL le tomo prestado a REYES, el Accumulation Bufer pero con una diferencia, en OpenGL solo hace referencia al búfer de color y se basa en un búfer de color extendido o varios búfers de color. A nivel doméstico la primera gráfica en implementarlo fueron las Voodoo 4 de 3Dfx a finales de los 90.

t-buffer3dacc

En Direct3D9 y OpenGL 2 serían adoptados como Multiple Render Targets y fue clave para la adopción del renderizado por diferido unos años más tarde.

deferred-v2

Pero su funcionalidad original que viene de REYES estaba centrada en el Antialiasing por muestras (MSAA), el Motion Blur y el Depth of Field que requieren para funcionar bien una gran cantidad de muestras.

Pero el Motion Blur y el Depth of Field cinemáticos requieren una ingente cantidad de muestras para funcionar… Lo que hace que el A-Buffer sea tremendamente enorme de cara al cine.

REYESABuffer.PNG

MotionBlur

Pero en juego a tiempo real no necesitamos el Motion Blur realmente por lo que lo podríamos descartar por completo.

Ahora bien, el trabajo de rasterizado y el trabajo de dibujar en pantalla vienen de manera combinada por lo que los rasterizadores se fusionarían con los ROPS.

Imaginemos que queremos renderizar una escena a 4K60, en micropolígonos esto es un mínimo de:

3840x2160x60= 498 millones de primitivas por segundo (micropolígono de 1 pixel)

3840x2160x60x2= 996 millones de primitivas por segundo (micropolígonos de 1/2 pixel)

Pero es en los ROPS donde se realiza el blending final por lo que seguiremos teniendo un array de micropolígonos por pixel relacionado con los MRT que en estos momentos es de 8 en las GPUS actuales, es decir, no iríamos a las 64-128 muestras pero si a 8 muestras por lo que:

3840 x 2160 x 60 x 8 muestras=3982 millones de primitivas por segundo

Y es aquí donde entremos en un problema gordo, porque necesitariamos que la tasa de rasterizado de la nueva GPU sea esa, y alto que es algo a lo que se puede llegar ahora con las GPUS de gama alta, el otro tema son los ROPS que es lo que viene a continuación y la respuesta a la pregunta… ¿Renderizamos a pantalla completa o por Tiles? Aquí no tenemos etapa de texturizado por lo que el clásico Sort-Last de OpenGL ha desaparecido y hay que tener en cuenta que REYES es una forma de renderizado Sort-Middle por lo que nos permite renderizar por Tiles la escena y con ello acabamos ordenando todo con Larrabee.

Cada uno de los núcleos de Larrabee tenía unos 256KB de memoria que podía servir como búfer de imagen para el Tile en concreto que se estaba procesando.

images.jpg

De ahí el Tile Rendering por Software, el problema para este planteamiento es que una Cache no es una RAM y el desarrollador no tiene control sobre su contenido realmente. ¿Que hubiese sido mejor? Pues una unidad con una SRAM internao scratchpad. ¿Os suena a algunos? Pues es que eso era lo que eran los SPE del CBEA que utilizaban un Scratchpad y por tanto la memoria se tenía que controlar manualmente. ¿Como lo aplicamos? Oh, es fácil y es algo que ya se esta haciendo actualmente.

VegaL2Cache

tiledcaching3

Dado que ahora se rasteriza por tiles y sobre la cache L2 y los ROPS tienen acceso a ella… ¿No vais viendo el mecanismo? No nos hace falta un scratchpad que controlar manualmente sino que nos encontramos con que el ROP-Rasterizador unificado en una sola pieza puede realizar el trabajo de rasterizado+blending sin tocar la memoria principal, y con esto terminamos la explicación de REYES y porque existe la idea que vamos a ver la evolución de la Rasterización a REYES.

Pe… pero Urian… la presentación de Sweeney es de 2009 y no ha cambiado nada de nada.

Si, porque los shaders no han evolucionado y siguen estando como hace unos años y DirectX 12 por ejemplo es una mejora muy pequeña respecto a DirectX 11 realmente. Las mejoras no llegan porque la mejora más obvia que es la micro-poligonización supone unos cambios enormes en el pipeline gráfico que subvierte el trabajo acumulado de años.

El fin del Larrabee y la GPU del futuro.

Larrabee fue «cancelado» en el 2010 aunque realmente su transformacion fue en el Xeon Phi que son la base de las tarjetas Knights… de Intel, utilizadas en el mercado de alta computación. El motivo de su cancelación es muy simple… No había software y los desarrolladores no se iban a romper los cuernos para colocar via software cosas que una GPU hace automaticamente con la función fija, irónicamente a Larrabee le ocurrió lo mismo que a la Irisvision.

s-l1600.jpg

La IrisVision fue una tarjeta 3D completa aparecida en 1991 hecha por SGI para IBM para sus PCs, y cuando digo completa me refiero con motor geométrico y todo, no tuvo apoyo porque utilizaba para programarse una cosa llamada IrisGL, algo marginal que con el tiempo evolucionaría a OpenGL… ¿El problema? Aunque ahora veamos a esto como un predecesor por aquel entonces no era un estandar y la mayoría de programas no podían utilizarla y el IrisGL/OpenGL no se utilizo hasta 1997 cuando John Carmack aposto por él para Quake 2 y SGI lo liberalizo en todas las plataformas.

Con Larrabee ocurrió lo mismo pero el gran problema de Larrabee fue el hecho de utilizar un núcleo de proposito general como era el P54C como base y los Knight siguen cayendo bajo el mismo error. Los shaders de las GPUS como comente en la entrada anterior están pensados para funcionar solamente con sus registros y la ventaja de ello es que la latencia de todas las instrucciones es la misma. No me voy a repetir en lo comentado en la entrada anterior, pero para los Shaders de una GPU para conseguir su máximo rendimiento es necesario que los datos a procesar estén en sus registros y el problema con Larrabee es que los datos se encontraban en cualquier parte de la jerarquía de memoria lo que provocaba cuellos de botella enormes.

¿Sabéis porque las GPUs son inmunes a la latencia? Pues por eso, no buscan nunca más allá de sus registros. El otro tema es el ancho de banda, el paradigma ideal es de 1 FLOP=1 Byte e independientemente del nivel de memoria en el que estemos el ancho de banda ha de ser este por lo que…

LarrabeeBandwidth

¿El motivo por el cual se mato al Larrabee? Ya os lo podéis imaginar. Por lo que una GPU futura que adopte de lo desarrollado con el Larrabee realmente debería continuar con el concepto de que los Shaders viesen solamente sus registros y realizar algunos cambios en sus Compute Units, pero tendría que realizar una Compute Unit de transición que permitiese pasar de la Rasterización a REYES.

Como he comentado más arriba el problema de las unidades de texturas es que con REYES son altamente ineficientes porque cualquier bloque de menor tamaño que 2×2 pixeles lo renderiza como uno de 2×2 pixeles por lo que si tenemos 4 micropoligonos unitarios…

NoMerge.PNG

Como eliminar las unidades de texturas sería un suicidio y rompería la compatibilidad hacía atrás entonces… lo que se ha propuesto deade hace años es lo siguiente:

Merge

Esto mantiene la compatibilidad de REYES con la Rasterización y si, se que REYES no tiene texturas propiamente dicho y tampoco tiene etapa de texturización. Pero la respuesta al problema es sencilla, la GPU no opera con el pipeline de manera fija hoy en día como ocurría en el 2009 gracias al soporte de los Compute Shaders, por lo que el problema de la falta de versatilidad ha sido eliminado. Lo otro es que es mucho más sencillo para los desarrolladores y los artistas un método híbrido donde el valor de color inicial sobre el que se aplican los shaders no sería un valor matemático sino que vendría de la textura a la que se haría referencia via las unidades de texturas.

¿Los otros cambios? Bueno, esto es algo complicado de explicar pero el concepto sería el de eliminar los ROPS de toda la vida y el Rasterizador y crear un nuevo tipo de unidad combinada colocada en cada grupo de Compute Units con la capacidad de escribir a un Tile Buffer también interno o directamente a la Cache L2 aunque para evitar conflictos de memoria sería suficiente con tener esa memoria tile buffer separada. El Rasterizador deberia ser capaz de funcionar en modo OpenGL o derivados, esto sería posible al estar conectado a los Shaders y dar la posibilidad de actuar a priori o a posteriori. ¿Haría falta algún cambio más? No, realmente no pero estos cambios serían necesarios para poder evolucionar a un pipeline tipo REYES sin perder la compatibilidad.

¿Y que nos podemos esperar? Hace unos años aparecio una demo llamada Euclideon que se basaba en este mismo concepto pero altamente ineficiente al hacerse en una GPU actual sin las optimizaciones.

Basicamente esto es micropoligonaje pero corriendo de manera eficiente por no correr en un hardware adecuado, pero el hardware adecuado es posible y no esta muy lejano realmente pero se necesita una arquitectura nueva.

Y si, con esto acabo, no quiero sobrecargaros de más.