Sega Saturn

sega_saturn_2s

La 32 bits de Sega no se pensó para competir contra la PlayStation de Sony en sus inicios sino contra la potencial amenaza que representaba 3DO y esto es importante para entender su hardware y como fue diseñado.

CPU

La CPU de Saturn es un doble Hitachi SH2 a 28Mhz aproximadamente, se trata del mismo procesador utilizado por la 32X pero a mayor velocidad y con una mayor cantidad de memoria RAM disponible, la potencia combinada de ambos chips es de 50 MIPS y al igual que ocurría con la 32X el segundo SH2 no hacía de CPU en conjunto con el primero sino que se utilizaba para la generación de la escena con la ventaja añadida de un sistema gráfico mucho más avanzado.

En comparación con la 3DO el SH2 maestro era el equivalente al ARM60 mientras que el segundo SH2 era el equivalente al co-procesador matemático. Ninguna de las dos consolas soportaba triangulos para componer las escenas 3D a tiempo real (por la forma en la que estaban diseñados sus Blitters) por lo que utilizaban Quads para componer las escenas en 3D a tiempo real, algo que se convertiría en una enorme desventaja para Saturn y un error de cálculo enorme para Sega. El caso es que Saturn es tomada como un mal hardware cuando salio al mercado, eso no es más que pura propaganda, comparada con lo que fue PlayStation si que era un hardware que se quedaba corto pero comparado con lo que Sega penso que sería su rival no se queda corta.

La consola de Sega era muy superior al estandar 3DO en lo que al 3D se refiere ya desde el principio.

Que si, que elDaytona USA de Saturn se ve horrible, lo se. Pero si miramos las cosas con perspectiva, el juego movía 60.000 pol/seg a una tasa de 20 fotogramas por segundo siendo un juego de lanzamiento de la consola, el original para Model 2 (un sistema mucho más capaz y pensado para el 3DO) movía 300.000 pol/seg a 60fps. Obviamente el juego se le quedaba muy grande a la Saturn pero… ¿Como es que a Sega le dio por presentar Saturn con este juego si la diferencia con el original era tan notable Pues por el hecho que esos 60.000 pol/seg era una cifra MUY SUPERIOR a lo que podían hacer Jaguar y 3DO, con las que Saturn limpiaba el suelo sin problemas.

El mayor handicap del doble Hitachi SH2 es que compartían bus directo hacía el SCU/DMA y por lo tanto no podían trabajar en paralelo, por lo que cuando los datos no se encontraban en la cache por lo que un procesador acababa por limitar al otro a la hora de procesar. Sí Sega hubiese mantenido un canal de memoria simultaneo para cada uno de los procesadores entonces hubieran sacado más rendimiento y menos dolores de cabeza en la programación de la consola.

SCU/DMA

No hace falta que os explique lo que es un DMA, de anteriores entradas lo sabéis. Dado que la memoria de la consola funcionaba a 14.3 Mhz, el SCU funcionaba a esa velocidad de reloj dado que era la velocidad de la RAM del sistema por lo que la comunicación entre los diferentes componentes del sistema se realiza a esa velocidad.

Saturn tiene tres buses internos distintos:

  • CPU Bus: Comunica directamente a los SH2 con la RAM principal sin pasar por el SCU.
  • Bus A: Utilizado para acceder al CD-ROM y el puerto de cartuchos, es controlado por el el SCU.
  • Bus B: Utilizado para comunicar la CPU con el VDP1, el VDP2 y el sistema de sonido de la consola.

La particularidad del SCU  es que contine un DSP por lo que se podía utilizar en paralelo a la CPU para operaciones matriciales, Existe la posibilidad de que el DSP dentro del SCU fuese originalmente el co-procesador matemático de la consola antes de colocar el segundo SH2 y ver que daba mejor rendimiento en ciertas tareas por lo que en la consola final el SCU quedo para gobernar los accesos a memoria y entre los diferentes elementos dejando el DSP interno en desuso y como legado de un diseño primigenio de la consola.

Expansión de memoria

Aunque no llegaron a occidente, Saturn tuvo una serie de cartuchos de expansión de memoria que fueron aprovechados por una serie de juegos.

KOF-95-Saturn-ROM-cartridge-1041428

El primero de 1MB y lanzado por SNK para su KOF95 añadía 1MB de ROM (no de RAM) que almacenaba en su interior los patrones/sprites más utilizados por el juego y aceleraba enormemente su carga, claro esta que la expansión de memoria más famosa fue la de Capcom:

SaturnExpansion4MB

 

Los 4MB adicionales no se sumaban a la memoria RAM principal sino que se accedían a través de un canal secundario, provocando que no hubiese contención con la CPU a la hora de acceder a la RAM principal.Como se puede ver en el siguiente diagrama de arriba del sistema el puerto de cartuchos se encuentra en un canal distinto a la RAM principal

VDP1

El VDP1 es un Blitter  de una naturaleza casi igual al subsistema gráfico de 3DO, con la diferencia que no tiene ningún tipo de contención con la CPU a la hora de acceder a la memoria RAM ya que la lista de comandos y los patrones/sprites/quads en pantalla se encuentran en una memoria de 512KB que el VDP1 lee para crear el búfer de imagen, el cual al igual que el 32X es doble solo que aquí el tamaño es de 256KB por cada uno de los búfers de imagen por lo que el total de memoria del VDP1 es de 1MB. Gracias al doble búfer y el hecho de no tener que leer de la RAM principal el nivel de contención de la memoria y el procesador gráfico era mucho menor, esto le daba una tasa de relleno mucho mayor.

No obstante el VDP1 tenia dos limitaciones muy grandes, el primero de ellos la falta de una cache de texturas, lo cual fue clave en el caso de PlayStation para alcanzar una alta tasa de relleno para los juegos, el segundo de ellos es la incapacidad para trabajar con triangulos para la generación de escenarios en 3D cuando el triangulo había sido siempre el estandar. El motivo de ello es que como he dicho antes la consola se diseño para competir contra 3DO y no contra la PlayStation de Sony por lo que el VDP1 estaba pensado para manipular patrones/sprites los cuales tienen cuatro vertices de referencia y no triangulos que es lo que se ha usado siempre como estandar en los gráficos en 3D a tiempo real.

Es por ello que los grafistas que hacían juegos para Saturn tenían que rascarse el coco para trabajar con modelados hechos por polígonos con cuatro vertices.

Esta particularidad no era muy bien vista por los desarrolladores que veían como todo el motor 3D que tenían desarrollado para otras consolas tenía que ser re-pensado en el caso de Saturn, así como los modelados de personajes en 3D y demás. Por otro lado hay que diferenciar entre los quads que son generados y polígonos que son dibujados, en el caso de Saturn (y en extensión 3DO) cuando las especificaciones de Saturn hablan de polígonos realmente se refieren a la cantidad de quads/patrones/sprites que el VDP1 puede plasmar en pantalla cada segundo. Cuando el VDP1 dibuja directamente sin tener que leer una textura de los 512KB, la parte de su memoria que es el búfer de imagen, entonces su tasa de dibujado es de 500K patrones/sprites/quads por segundo, cuando tiene que hacer una operación de lectura adicional para el mapeado de texturas la cosa baja a los 200K patrones/sprites/quads por segundo.

La configuración de memoria del VDP1 era de 16+16 bits (lectura+escritura) accediendo a los dos bancos al mismo tiempo, la memoria de cada uno de los bancos funcionaba a 14.3Mhz por lo que la tasa de relleno era de 14.3 Mpixeles/seg, algo que si miramos la siguiente tabla resulta un cuello de botella enorme ya que el VDP1 podía generar sobre su búfer de imagen un pixel por cada ciclo de reloj:

VDP12

 

¿Que hubiese pasado si el VDP1 hubiese tenido a su disposición una memoria a 28.6 Mhz? Pues claramente el rendimiento de la consola hubiera crecido enormemente de cara al 3D y aunque la limitación de los quads hubiese seguido existiendo la tasa de fotogramas por segundo de los juegos en 3D hubiese sido mucho mayor. El problema es que incluso con la memoria a la velocidad adecuada Saturn hubiese seguido con una ligera desventaja en cuanto a la velocidad de relleno respecto a la PlayStation de Sony y es que comparar la GPU de PSX con el VDP1 de Saturn (las dos piezas equivalentes en ambas consolas) hace que la consola de Sega palidezca pero es que esta no fue diseñada en principio para el 3D sino para ser una bestialidad en cuanto a 2D y todo ello gracias al segundo procesador gráfico, el VDP2.

VDP2

El VDP2 es llamado “Background Processor”, su trabajo es el de generar la pantalla final combinando los diferentes planos/fondos con el búfer de imagen generado por el VDP1, tiene a su disposición unos 512KB de memoria divididos en cuatro bancos de 128KB cada uno de ellos a los que puede acceder para leer o escribir.

  • Puede leer el búfer frontal (mientras el VDP1 genera el búfer trasero) del VDP1 y manipularlo como si fuese un patrón/sprite con muy pocas instrucciones al vuelo y sin intervención de la CPU. Por ejemplo puede rotar a tiempo real todo el búfer de imagen sin que la CPU y el VDP1 tengan que calcular y rotar uno por uno los patrones/sprites.
  • Puede generar cuatro planos de scroll y dos planos rotatorios en una misma imagen: VDP2
  • Si se utilizan dos planos de rotación al mismo tiempo entonces los planos de scroll normales no se pueden realizar.
  • El VDP2 puede aplicar efectos de transparencia sobre los diferentes elementos, eso si, la transparencia es del tipo aditiva y no multiplicativa por lo que su precisión es menor. Este truco es utilizado por juegos como Burning Rangers y Grandia para aplicar transparencias.
  • El VDP2 puede operar a nivel de pixel, patron/sprite/quad, búfer de imagen entero a la hora de realizar una manipulación.

La siguiente serie de videos demuestran las virguerias visuales a nivel de gráficos en 2D que se podían hacer gracias al VDP2.

Pese a que el VDP2 esta conectado al VDP1 es posible renderizar la escena prescindiendo por completo del VDP1 ya que el SCU/DMA da acceso directo al VDP2 hacía la CPU y la RAM principal. Algunos juegos renderizan directamente sobre el VDP2 sin tocar el VDP1 para aprovechar la enorme ventaja que tiene el VDP2 es su mayor ancho de banda y por tanto el hecho de poder dibujar la escena a 28.6 Mpixeles/seg de tasa de relleno. Sea cual sea el caso en Saturn el hecho que el VDP2 sea el que este conectado a la salida de video hace que no sea posible prescindir por completo del VDP2 en la composición de la escena.

Conclusión.

Saturn es una consola que si hubiese corregido algunos errores de diseño no habría tenido los problemas que tuvo. En primer lugar el hecho de darle al segundo SH2 un pozo de memoria propio para la geometría de la escena hubiese subido la tasa de polígonos en los gráficos en 3D, en segundo lugar el soporte para triangulos en el VDP1 hubiese sido un acierto, así como asignarle una memoria mucho más rápida y el hecho de poder dibujar en pantalla directamente sin intervención del VDP2, dejando el VDP2 eso si, para gráficos en 2D. Aunque lo mejor hubiese sido crear un SuperVDP de 1MB con las capacidades de ambos, pero Sega se obsesiono en que no quería chips únicos muy grandes sino muchos pequeños por el hecho que supuestamente le costaban más baratos, eso fue un error enorme ya que al final acabaron sobrecomplicando la consola y haciendo que esta fuese mucho más cara.

Sony PlayStation

PlayStationConsole1

Esquema General

PU-23(a)_blocks

En lo primero en que me voy a centrar es en la CPU del sistema.

R3000 CPU

La CPU de PlayStation era un MIPS R3000A altamente modificado por Sony y fabricado por LSI para esta funcionando a 33.86 Mhz y con una potencia de 30 MIPS.

R3000PSX

Las primera modificación se encuentra en el núcleo principal de la CPU, en vez de tener una cache de datos de primer nivel, Sony añadió una memoria Scratchpad de 1KB, a la que la CPU puede acceder a una velocidad de 133.4 MB/seg, dado que no accede a través del controlador de la DRAM siempre esta accesible, incluso cuando otro dispositivo accede a la RAM principal a través del DMA.

Sí seguimos dentro del chip pero ya fuera del núcleo de proposito veremos la unidad SIO (E/S en serie) que es la que comunica la CPU con los periféricos (mandos y memory cards), las unidades B/U, MDEC y GTE son los tres co-procesadores a medida creados por Sony para el R3000A de PlayStation.

B/U

La unidad B/U es lo que llamamos DMA, es la unidad que se encarga de manejar el acceso a la RAM principal tanto al resto de procesadores del sistema que no son la CPU y las interrupciones de esta a la propia CPU. Hay que tener en cuenta que cuando uno de los procesadores accede a la memoria principal la CPU es desconectada de dicha memoria mientras dure la operación con la memoria. Cada co-procesador y procesador de apoyo esta conectado con la RAM a través de un canal DMA, cuya lista es la siguiente:

La lista de canales de la unidad DMA es la siguiente:

  • El Canal 0 sirve para transmitir los bloques de datos comprimidos dese la RAM principal al MDEC.
  • El Canal 1 comunica el MDEC con la RAM para que este transmita los bloques ya descodificados hacía la RAM.
  • El Canal 2 comunica con la VRAM.
  • El Canal 3 sirve para comunicar con el CD-ROM.
  • El Canal 4 es para la unidad de procesamiento de sonido (SPU).
  • El Canal 5 comunica con el Puerto de E/S paralelo, dicho puerto no se uso y fue descartado en versiones posteriores de la consola.
  • El Canal 6 comunica con la GPU con la RAM principal.

MDEC

El segundo coprocesador es el Movie Decompression (MDEC)/Motor de descompresión de películas. Se encarga de la descodificación de vídeo en MPEG-1/H.261 para las escenas cinemáticas, fue una novedad importante por el hecho que hasta la llegada de PlayStation se utilizaba la CPU misma para renderizar las escenas cinemáticas que empezaron a incluirse en los juegos basados en CD-ROM.

El MDEC solo se encuentra activo cuando hay una escena cinemática, comparativamente con el R3000A tiene una potencia de 80 MIPS pero no se trata de un procesador de proposito general sino una máquna de estado que lo que hace es descodificar el video en bloques que la GPU de PlayStation puede entender, su funcionamiento es el siguiente:

  1. Recibe los datos a través del canal del DMA hacía el MDEC y los descodifica al vuelo.
  2. Dicha descodificación al vuelo la almacena en la memoria principal.
  3. Los bloques descodificados son enviados al búfer de imagen de la VRAM para que sean mostrados en pantalla.

GTE

Llegamos a la joya de la corona, el GTE es un co-procesador especializado en realizar ciertas operaciones con vectores y matrices que son ampliamente utilizadas para la generación de gráficos en 3D a tiempo real, no tiene acceso a la RAM principal y la única manera de acceder al mismo es a través de llamadas a los registros del mismo a través de la CPU por lo que se puede considerar más bien un co-procesador matemático del R3000A para realizar dichas operaciones.

¿Que tiene de especial? Pues que para la época era una bestia parda. La segunda consola más potente cuando salio PlayStation era la Sega Saturn que se encargaba de la geometría de la escena utilizando el SH2 esclavo para dicha tarea. Aunque mucho más versatil a la hora de desarrollar el SH2 requeria que ciertas funciones que en el GTE eran una simple llamada al registro correspondiente se tuviesen que hacer manualmente a través de código y esto es lo que hacía a la PlayStation de Sony más atractiva que otros sistemas en cuanto al 3D. Cosas tan complejas como la rasterización en PlayStation eran una simple llamada a la instrucción correspondiente.  El otro motivo era la velocidad con la que el GTE realizaba sus cálculos, tened en cuenta que el SH2 de Saturn tenía una potencia límite de 25 millones de instrucciones mientras que la del GTE era de 66 millones, esto es algo más del doble y esto significaba que se conseguían las mismas tasas geométricas que con Saturn pero con un esfuerzo mucho menor.

A nivel visual el punto fuerte del GTE era la capacidad para soportar vertex lightning, se conseguía dando un valor de color concreto a los vertices para que las aristas de estos se difuminaran con el color del poligono o la textura más cercana. A la técnica se la llama Gouraud Shading y aunque Saturn en teoría era capaz de aplicarla lo hacía utilizando una formula mucho menos efectiva y que destruía el colorido de la escena.

_SHADING

 

La tasa geométrica de los primeros juegos de PlayStation y Saturn era más o menos parecida, durante años muchos juegos de la consola de Sony se movieron por esa tasa pero fue gracias al Gouraud Shading bien aplicado que los juegos parecían realmente más pulidos, en especial los exclusivos.

Ahora bien, PlayStation era muy primitiva a la hora de renderizar la escena en 3D, uno de los elementos más prohibitivos en aquella época era el uso de un búfer de profundidad, un búfer de profundidad es un búfer de imagen en que en cada pixel no se almacena la información de color sino su distancia respecto a la cámara. En 1994 dar soporte a esto era prohibitivo por lo que Sony había descartado su uso en la consola y tomo un mecanismo completamente distinto que son las tablas de ordenación. En el SDK de la consola se puede leer:

La GPU de PlayStation esta diseñada para leer una lista enlazada de primitivas gráficas y dibujarlas todas en secuencia hasta que se llega al final de la lista. Hay muchas formas en las que esta lista puede ser construida pero las librerías de la GPU de PlayStation utilizan un método conocido como”Tabla de ordenación” porque provee la lista de pantalla de una forma flexible y fácil. Este método es ideal pera gráficos en 3D, pero es también aplicable a los gráficos en 2D donde el orden de dibujado es importante.

Una lista de ordenación (OT) es una lista enlazada diseñada para agrupar juntas primitivas gráficas para el 3D (polígonos, segmentos de linea, sprites, etc) de acuerdo con su valor de profundidad (Z). Cuando la lista se utiliza para dibujar, los elementos que estén más alejados de la cámara serán los que se dibujaran primero, los más cercanos a la cámara los que se dibujaran más tarde, y todos los que estén en una distancia intermedia se dibujaran cuando sea apropiado.

Esto significa que la escena es dibujada de atrás hacía adelante por lo que los objetos que quedan por detrás de otros también son dibujados en el búfer de imagen cuando se compone la escena.

 

Ya os hable de dichas tablas hace unas entradas:

PSXOrdering2

A través de una instrucción especial, el GTE transforma las coordenadas (X, Y,Z) en coordenadas (Xs,Yz), cuando la GPU recibe los fragmentos no sabe si cada uno de ellos se encuentra detrás o delante de otros por lo que tiene que consultar la tabla donde tiene almacenado el orden en el que tiene que dibujar los objetos. Dado que 256 valores es algo muy impreciso se pueden anidar varias tablas conjuntas para aumentar la precisión. El envió de las tablas a la VRAM para que la GPU las pueda leer se hace a través del canal 6 del DMA.

Memoria Principal

PlayStation disponía de 2MB de RAM, dicha memoria funcionaba a 33Mhz y era capaz de transmitir hasta 4 bytes (32 bits) por ciclo de reloj. En modo lectura+escritura transmitía 16+16 bits. Comparativamente con todos los pozos de memoria que hemos visto hasta ahora la de PlayStation es la más rápida de todas ellas, siendo su pico mayor que el de la Atari Jaguar pero sin la desventaja de tener un solo canal de acceso.

VRAM

La VRAM tiene el mismo ancho de banda que la RAM principal, unos 66.7 MB/seg. Esta compuesta como si se tratase de un enorme búfer de imagen de 1024×512 pixeles y 16 bits (2 bytes) por pixel (1MB). Se trata de una RAM de doble puerto como la de 3DO por lo que mientras se esta escaneando la imagen ya generada para ser enviada al televisor se esta renderizando la siguiente en otra parte de la memoria. La diferencia respecto a 3DO es que la VRAM es ahora memoria origen y memoria destino para no parar a la CPU por lo que es necesario cargar todos los datos necesarios para los gráficos a la VRAM antes de empezar a renderizar la escena.

Dichos datos se almacenan en forma de página de texturas. Cada página de texturas tiene un tamaño de 256×256 pixeles con una información de 4, 8 o 16 bits por pixel (este último es de 15 bits+1 bit para marcar si el pixel es transparente/no se dibuja). Esto hace que el tamaño que ocupan las páginas de texturas sea variable dependiendo de la información que almacene cada una de ellas. La información y el número de paginas de texturas que se puedan almacenar en memoria dependerá directamente de la memoria libre que le deje el búfer de imagen.

En cuanto a las resoluciones soportadas por la consola y lo que ocupaban cada una de ellas, sí la resolución era muy alta entonces no se podía operar con doble búfer de imagen y se tenia que renderizar la escena durante el VSync, recortando enormemente el rendimiento de la misma:

PSXResolutionsLas resoluciones entrelazadas iban a 60 fotogramas por segundo, las no-entrelazadas a 30 fotogramas por segundo.

GPU

El chip gráfico de PlayStation es un animal particular por el hecho que esta especializada en dibujar triangulos, el motivo de ello es que es el estándar para las escenas en 3D a tiempo real ya que cualquier forma poligonal se puede romper en triangulos. Se podría definir al chip gráfico de PlayStation como un dibujador de triangulos 2D.

Debido a esta particularidad para dibujar el clásico patrón/sprite de forma cuadrada lo que hace es dibujar dos triangulos juntos como si fuese un cuadrado. Lo que es la preferencia de los pixeles (las diferentes capas para el 2D) se realizan utilizando las Ordering Table para colocar los diferentes fondos que componen la escena. Esta particularidad de la consola de Sony obligaba a los desarrolladores a plantear el motor gráfico de sus juegos en 2D de forma diferente a cualquier otro sistema.

Lista de Comandos

La GPU recibe dos listas de comandos, GP0 y GP1, en la primer recibe las listas de comandos y los patrones/fragmentos/sprites generados (o no) por la CPU (GTE) a través del DMA2 como origen y la VRAM como destino. El GP1 en cambio sirve para acceder a ciertos registros para seleccionar cosas como el modo de resolución, mandar a limpiar la VRAM al completo…

Tasa de polígonos.

La tasa de polígonos depende de muchas cosas, en realidad nos debería importar unicamente la cantidad de polígonos que puede dibujar la GPU en pantalla pero eso depende también del resto de pasos previos. ¿Cual es la carga de trabajo del GTE? ¿Cual es la carga de trabajo durante la etapa de texturizado? ¿Cual es la calidad del código? La tasa de poligonos en ninguna consola es fija ya que depende de muchos factores.

Texturizado

PlayStation soporta mapeado de texturas, puede texturizar desde la VRAM o desde la cache de texturas.

Sí lo hace desde la VRAM entonces puede manejar como si fuese un solo objeto una página de texturas de 256×256 pixeles. Pero antes de acceder a la VRAM mirará si la información se encuentra en la cache de texturas, dicha cache de 2KB almacena en su interior una pequeña porción de la página de texturas y será a la que accederá antes que la VRAM por jerarquía, sí la información no se encuentra en la cache de texturas entonces se pasaba a la VRAM. La cache de texturas es un estandar de todos los procesadores gráficos ya que permite reducir el número de lecturas a la RAM y dada su menor latencia aumenta la velocidad de renderizado. No obstante la cache de texturas es solo de lectura y la composición final sobre la escena se hace escribiendo sobre la memoria de video.

El otro punto a tener en cuenta es que dado que los datos que llegan desde el GTE no incluyen búfer de profundidad por lo que el texturizado no se hace desde la perspectiva correcta por lo que las texturas tiemblan, algo que ocurre dado que esto en aquella época es que permitía simplificar el mecanismo de texturizado.

El texturizado desde desde una perspectiva correcta tiene la siguiente formula:

CorrecciónPerspectiva

En cambio el texturizado tal y como lo hacen PlayStation, Saturn, 3DO… utilizaba esta otra formula:

TexturizadosinZ

 

Mucho más fácil de implementar pero que llevaba consigo el problema de los “flangolinos”.

Tasa de relleno.

La gran ventaja de PlayStation respecto a su competencia de la época era su enorme tasa de relleno, el gran error de Sega con Saturn y que la dejo atrás de PlayStation fue el tema de la tasa de relleno (fill rate) de cara a los gráficos 3D:

oh-no

 

En Saturn se renderizaba la escena de la siguiente manera:

  • El VDP1 escribe el búfer de imagen sobre uno de los dos búfers de imagen que tiene este utilizando un ancho de banda a 14.3Mhz y de 8 bits para la escritura.
  • Una vez ha sido dibujado la memoria que lo contenía pasa a ser el búfer delantero y el antiguo búfer delantero pasa a ser el búfer trasero.
  • El VDP2 lee el búfer delantero y lo copia en su búfer de imagen como si fuese uno de sus planos, aquí puede combinarlo con otros planos generados en el VDP2 o dibujar lo visto en pantalla.

El hecho de hacer transmisiones entre diferentes memorias añade latencia y afecta a la tasa de relleno, si a esto le sumamos que el ancho de banda de escritura es de 8 bits mientras que el de PlayStation es de 16 bits esto significa que la consola de Sony dobla en el ancho de banda de escritura y gracias a ello puede doblar en cuanto a tasa de relleno. Pero es que además simplifica enormemente las cosas:

  • LA GPU escribe en la VRAM con un ancho de banda de 16.67 Mhz y 16 bits de velocidad de escritura.

Dicho de otra forma:

keepitsimple

Dado que la tasa de relleno esta relacionada con la geometría la forma en la que Saturn podía mantener el tipo frente a PlayStation era reducir la información de color por pixel. Las diferencias entre ambas consolas se empezarón a notar con el port de Tomb Raider a PlayStation, un juego en cuya versión de PlayStation no solo incluyo texturas semitransparentes sino que operaba con una resolución de color mucho mas alta.

compare_water

Alpha Blending y multitextura.

Alpha Blending es lo que se llama la mezcla con el canal alpha para texturas semitransparentes, para poderse ejecutar se necesita primero leer la textura, escribirla sobre memoria y luego volverla a leer por lo que disminuye enormemente la tasa de relleno. Una variación de la mismo se utilizo al final de la vida de la consola para ejecutar efectos de multitexturizado muy simples.

El Alpha Blending es algo que solo las consolas a partir de PlayStation en adelante pueden realizar. En realidad las transparencias se siguen calculando de la misma manera que en PlayStation ya que es la forma estandar de realizarlo. Consolas como Saturn y 3DO realizaban transparencias a nivel de capas. Renderizaban la escena en 2D y componían esta por diversas capas por lo que las transparencias se simulaban dejando ver la capa posterior.

compare_underwater

Nintendo64

4-original-nintendo-64Las entrañas de la consola se pueden ver en la siguiente imagen:

rev4n64smallselected

Las dos piezas rectangulares es la memoria RAM del sistema, la que esta justo encima es el Reality Co-Processor, el chip a la izquierda es la CPU del sistema.

CPU

El NEC VR43000, una versión del MIPS R4300i fabricada por NEC para Nintendo, era la CPU de N64. Con unos 93.75Mhz, dicha CPU estaba sobre el papel una generación por encima de la de PlayStation llegando a ser teóricamente más de tres veces más potente que la CPU del R3000A de PlayStation.

R4300i

Mientras que el R3000A de PlayStation tenía tres co-procesadores aquí solo tenemos uno (el COP0) que se encarga de dos funciones por un lado la MMU (no confundir con la unidad DMA) y por otro lado de las interrupciones del sistema. Dicho COP0 es muy similar a la unidad B/U del R3000A de PlayStation pero sin las funciones DMA de este ya que el controlador de memoria y la unidad DMA se encontraba en el RCP.

RAM del sistema.

N64 tiene unos 4 MB de memoria RAM del tipo RDRAM, la velocidad de reloj de la misma es de 250 Mhz pero con un ancho de banda de 9 bits y siendo el bus bidireccional (lectura+escritura) dando un ancho de banda de 562.5MB/seg sobre el papel.

El controlador de memoria y la unidad DMA se encontraban en el RCP. La consola podía expandir la memoria a 8MB a través del expansion pak, pero dicha memoria no aumentaba el ancho de banda de la misma.

El problema de la latencia.

El problema de la RDRAM es que su latencia depende de la distancia existente entre el procesador y el controlador de memoria, en el caso de N64 la CPU no tenía acceso directo a la memoria y tanto la unidad DMA (encargada de controlar el tráfico hacía la memoria de los diferentes procesadores) como el controlador de memoria RDRAM (encargado de realizar la comunicación de la unidad DMA con la RDRAM) se encuentran en otro chip. Esto añadía una latencia enorme para el acceso a la memoria por parte de la CPU. Sí encima a esto le añadiamos que la RDRAM solía tener una mayor latencia que la SDRAM pues teníamos una situación donde la potencia de la CPU quedaba altamente reducida por culpa de este problema.

PlayStation 2, otra consola en la historia que utilizo RDRAM tenía el controlador de memoria dentro del Emotion Engine para disminuir la latencia. En el caso de Gamecube esta heredo la arquitectura general de N64 pero escogio una RAM con menor latencia (1T-SRAM de MoSys) y añadió una cache de segundo nivel a la CPU para paliar el problema de la latencia.

¿Pero como afectaba esto al rendimiento gráfico? Pues teniendo en cuenta que la CPU es el primer componente en el pipeline gráfico, realmente mal. Hay que recordar que la primera etapa en el renderizado 3D es la de aplicación que depende de la CPU y una CPU con un cuello de botella en ese aspecto significa que las etapas posteriores se ven afectadas y en N64 se veían altamente afectadas y de ahí las tasas de fotogramas tan bajas en los juegos.

N64pipeline

El resultado eran juegos con una tasa de fotogramas por segundo muy baja en comparación con la competencia directa. Lo cual significa que el sistema era altamente defectuoso en cuanto al diseño y el funcionamiento del mismo y pese a su enorme potencia todo se iba por el fregadero por culpa del problema de la latencia.

Cartuchos.

La diferencia entre un cartucho y el CD-ROM es que el cartucho se puede tratar como una memoria más mientras que el CD-ROM requiere volcar los datos a memoria. En el desarrollo de Nintendo64 tuvieron el dilema de CD-ROM o más memoria y dado que SGI creía que la memoria no bajaría de precio pensaban que poner más memoria a la consola les daría una ventaja sobre la competencia. Esto lo comente en una entrada hace unos tres años.

La CPU y el RCP podían acceder a los datos de los cartuchos con un bus paralelo al de la memoria RAM. El ancho de banda de los cartuchos dependía de la velocidad de la ROM en estos, que podía ir de los 5MB/seg a los 20MB/seg dependiendo del tipo de ROM utilizada en los cartuchos. Lo habitual era copiar los datos del cartucho a la RAM del sistema pero si al ancho de banda de las ROMs era lo suficientemente alto entonces la CPU podía leer los datos que no son sensibles al ancho de banda desde el cartucho sin tener que pasar por la RAM.

RCP

El Reality Co-Processor funciona  a 62.5Mhz. El esquema del RCP es el siguiente:

1-2-3-2

Esta compuesto por tres piezas fundamentales dentro, la primera de ellas es el controlador de memoria y la unidad DMA de la consola, el segundo es el subsistema gráfico que esta compuesto por dos procesadores llamados Reality Signal Processor y Reality Display Processor,el tercero la unidad de E/S. Me centrare solo en el RCP y el RSP.

El RSP es un MIPS R4300i como la CPU pero su tarea no es hacer de CPU sino encargarse de:

  • La geometría de la escena
  • Generación del Audio de los juegos.
  • Procesador de Comandos del Sistema Gráfico.

No obstante no es igual a la CPU por varios motivos:

  • Carece de registros de 64 bits.
  • La unidad de prediccion de saltos ha sido eliminada.
  • Las instrucciones de multiplicación y división por enteros no se encuentran disponibles.
  • Como se puede ver en el diagrama de arriba su cache datos e instrucciones es mucho menor.

En cuanto a su configuración en co-procesadores es distinta a la de la CPU, el COP0 fue sustituido por una unidad vectorial. Este tipo de unidades permiten aplicar una misma instrucción por ciclo a una colección de datos por ciclo de reloj. Lo cual va muy bien en la manipulación de vertices ya que la mayoría de instrucciones de la geometría de escena se basan en aplicar la misma instrucción en diferentes operandos.

Aunque a simple vista su funcionalidad es la misma que la del GTE de PlayStation la diferencia es que la unidad vectorial del RSP es de proposito general y o específico por lo que no es una colección de máquinas de estado realizando una serie de operaciones de cara el 3D. Al ser una unidad de proposito general, y dado que el RSP es un R4300i modificado lo que hace es ejecutar una lista de instrucciones de forma recursiva que se encuentran en su cache de instrucciones. En este aspecto su comportamiento era muy parecido al de la GPU de Jaguar, ejecutaba un micro-código que marcaba como se tenía que comportar el RSP. A lo largo de la vida de la consola aparecieron varios micro-códigos distintos:

  • Fast3D: El oficial de SGI y Nintendo es el que es más preciso en cuanto a imagen pero el menos adecuado para un videojuegos debido a que sacrifica velocidad por precisión de imagen. No obstante los desarrolladores externos a Nintendo y Rare no pudieron acceder a las entrañas del RSP para modificar el micro-código hasta muy avanzada la vida de la consola.Su rendimiento era de 100K poligonos/segundo en modo “1-Cycle” y 50K poligonos/segundo en modo “2-Cycle”.
  • Turbo3D: No utilizado en los juegos, desactivaba el bufer de profundidad, la corrección de perspectiva y renderizaba solo en modo “1-Cycle” con un rendimiento de 600K pol/seg. Nintendo nunca dejo que este modo fuese utilizado en ningún juego comercial.
  • Micro-códigos específicos: Desarrolladores como Boss Game Studios, Factor5, Rare y otros llegaron a desarrollar sus propios micro-códigos.
  • Sprite 2D: Utilizado en los juegos en 3D de la consola.

La forma en que la CPU se comunicaba con el RSP para enviarle el microcódigo primero y las listas de pantalla no era a través de un bus de comunicación directo sino que escribía la lista de instrucciones y datos en la RDRAM, dada la latencia entre la CPU y la RDRAM esto era un problema enorme de rendimiento. Nintendo en Gamecube soluciono esto haciendo que la CPU se pudiese comunicar con el subsistema gráfico sin pasar por memoria.

Conexión RSP-RDP

Un bus de 128 bits a 62.5Mhz, esto significa una conexión de 1GB/seg, más que suficiente para pasarse datos sin ningún tipo de limitacion y/o cuello de botella.

Reality Display Processor

Rasterizer

N64 fue la primera consola de videojuegos en tener un rasterizador/triangle setup por hardware que realizaba dicha tarea de forma automática.

Z-Buffer

Cuando el rasterizador proyecta en un espacio 2D los datos 3D que le ha enviado el RSP tiene la opción de almacenar los datos de profundidad de cada pixel en un búfer de profundidad.  N64 no fue la primera consola en tener un búfer de profundidad, ese honor le pertenece a Jaguar. Pero la primera en tener una implementación que fue “usable” fue en N64.

El handicap del Z-Buffer en N64 es que de los 9 bits por ancho de banda de la RDRAM utilizaba el noveno para el dicho búfer. Teniendo en cuenta que la tasa de relleno del RCP es de 62.5 Mpixeles/seg y el Z-Buffer es de 2 bytes (16 bits) entonces se necesitarían unos 125 Mbytes/seg, pero el sistema de memoria de la consola solo otorgaba unos 62.5 Mbytes/seg para esta tarea por lo que la tasa de relleno general del sistema pasaba a ser de 31.5 Mpixels/seg ya que tanto el búfer de profundidad como el de color han de ser parejos y por tanto el uso del búfer de profundidad reducía la tasa de relleno a la mitad.

Texture Unit

El Texture Engine hace el mismo trabajo que el de cualquier otra unidad de texturas vista hasta ahora pero tiene la particularidad de que las texturas solo pueden ser de 4KB como máximo. El motivo por el cual N64 solo puede leer las texturas desde la cache de texturas para procesarlas tiene una explicación muy simple y es que el Texture Filter realiza el filtrado texturas bilineal y necesita unos 4 accesos a la memoria por pixel a procesar, si no se tuviese la cache de texturas entonces la RAM no podía dar el suficiente ancho de banda de lectura para aplicar este filtro gráfico.

La ventaja de PlayStation respecto a N64 es que si no encontraba la textura en la cache de texturas entonces se ponía a leerlas de la página de texturas de la VRAM sin perdida de rendimiento alguno. La cache de texturas de N64 tendría que haber sido capaz de almacenar texturas a una resolución de 256×256 pixeles y 16 bits de color. Esto son unos 128KB de cache de texturas, lo cual era prohibitivo para la época. La otra solución hubiese sido aumentar el ancho de banda de la consola hasta los 62.5*2*4 bytes de ancho de banda, lo cual también era prohibitivo. Por lo que la mejor opción hubiese sido colocar una cifra mayor que los 4KB de cache de texturas.

Con tal de paliar el problema de la cache de texturas los desarrolladores utilizaban varios trucos, en los juegos que no eran de corte realista se utilizaban texturas de 16 colores+Gouraud Shading, otros en cambio separaban las texturas en grupos pequeños en comparación a sus contrapartidas en otros sistemas.  Esto se ve muy bien comparando los assets de las versiones de Resident Evil 2 de N64 y PSX donde las texturas en el caso de N64 han sido fragmentadas en otras más pequeñas:

RE2N64

¿La ironía? En PSX y Saturn se utilizaban grandes cantidades de polígonos en N64 se utilizaba unos pocos pero muy grandes, el motivo de de ello es el texturizado con corrección de perspectiva, gracias a que N64 utilizaba un búfer de profundidad era posible texturizar poligonos de gran tamaño sin que esto se vieran distorsionados. La diferencia entre el texturizado con corrección de perspectiva y sin él se puede ver en el siguiente video:

Esto que en principio era una ventaja se convertía en una desventaja por los 4KB de texturas. Sabéis lo que ocurre cuando estiramos una imagen muy pequeña en un espacio muy grande? Pues esto es lo que le pasaba a N64 en areas donde utilizaba polígonos muy grandes. Dado que el tamaño máximo era solo de 32×32 pixeles esto perjudicaba la calidad de las texturas cuando estas se alargaban.

Color Combiner

El Color Combiner es unidad Fragment/Pixel Shader primitiva, para entender su funcionamiento tenemos que entender el concepto de los Shade Tree de Robert L. Cook.

captura-de-pantalla-2013-02-23-a-las-11-21-42-1

La idea de los Shade Tree es la de generar una textura de forma procedural a través de operaciones con sucesivos valores del color y el alpha hasta conseguir el resultado deseado. En el caso de Nintendo64, SGI implemento una pieza llamada Color Combiner en el pipeline gráfico.

Captura de pantalla 2013-05-16 a las 14.52.46Captura de pantalla 2013-05-16 a las 14.54.50Captura de pantalla 2013-05-16 a las 14.55.50

Uno de los efectos curiosos que permitía el Color Combiner era el Mario Metal de Super Mario 64.

246950-super-mario-64-nintendo-64-screenshot-metal-mario-in-hazy

El Color Combiner de N64 podía trabajar con una textura o con dos texturas para realizar sus operaciones.

Captura de pantalla 2013-05-16 a las 13.25.13

Captura de pantalla 2013-05-16 a las 12.09.09

El Color Combiner se encargaba de muchos de los efectos visuales de la consola y Nintendo lo hizo evolucionar en Gamecube siendo el conocido TEV de dicha consola. La diferencias respecto a su sucesor es que mientras Gamecube tenia una enorme cache de texturas desde la que operaba con varias texturas, en N64 solo se podía operar con una textura en memoria, esto significa que lo que se hacía era cargar la textura en la cache de texturas, procesarla y a continuación volverla a cargar en el siguiente ciclo. Esto obviamente reducía la tasa de relleno a la mitad y si tenemos en cuenta que la tasa de relleno ya se veía afectado por el búfer de profundidad entonces tenemos que utilizando el renderizado en dos ciclos la tasa de relleno acaba sien

Blender y Tasa de Relleno

Se le llama Blender por el hecho que trabajo es el mezclar los pixeles creados por la unidad de texturas con los píxeles del búfer de imagen. Es en esta etapa se realiza el Anti-Aliasing por un lado y por el otro el Alpha Blending (efectos de semi-transparencia). Hay que tener en cuenta que la aplicación de ambos efectos en los juegos reduce aún más la tasa de relleno de la consola y aquí es donde entra el problema que antes quería comentar.

El rendimiento de la tasa de relleno dependía directamente del modo gráfico utilizado:

N64Fillrate

Sí el RDP no tenía que texturizar nada (flat shading) o en su defecto la composición era de una imagen 2D entonces su tasa de relleno era de 250 Mpixeles/seg con 16 bits de color y 125 Mpixeles/seg con 32 bits de color. COPY se refiere a copiar un sprite/patrón/textura ya generado y en cuanto a 1CYCLE y 2CYCLE se refiere a la tasa de relleno respecto si utilizamos efectos gráficos que requieren uno o dos ciclos completos para generarse (ver la sección del Color Combiner de más arriba).

Hay que tener en cuenta que debido a la implementación del búfer de profundidad en el caso de los modos “1-Cycle” y “2-Cycle” la tasa de relleno se reducía directamente a la mitad. No es que N64 estuviese limitado por geometría sino que estaba limitado en cuanto a la tasa de relleno.

Resolución y Búfer de Imagen

La RDRAM era de doble canal por lo que el sistema soportaba doble búfer, así pues al igual que el resto de sistemas de la época podía generar el búfer de imagen mientras se estaba leyendo el generado previamente para ser enviado al televisor.

N64 soportaba las siguiente resoluciones:

  • 256×224
  • 320×240
  • 640×480 (no-entrelazado)

La última resolución se utilizaba con los juegos que utilizaban la expansión de memoria aprovechando la mayor densidad de memoria disponible en el sistema para almacenar los búfers de imagen.