He podido acceder al SDK de PlayStation 4, bueno… A una versión que circula por la red y a la documentación asociada al mismo y sinceramente el nivel de detalle en la documentación me ha abrumado enormemente y al mismo tiempo me ha servido para conocer una serie de informaciones que no se encuentran dentro de las notas de prensa y lo mostrado al público tanto de PlayStation 4 como de PlayStation 4 Pro. Me gustaría encontrar algo similar de Xbox One y Xbox One X… Pero no lo he encontrado por el momento.

Máximos Teóricos

Las cifras que pongo a continuación entran en conflicto con lo que mostrare después, pero se ha de tener en cuenta es que lo mostrado en las tablas de la sección de abajo son máximos reales a nivel práctico y lo que vemos aquí son máximos teóricos.

Es importante sabe que los anchos de banda máximos nunca son alcanzados.

Organización y Acceso a la Memoria

El primer punto importante es como estan organizados los canales del SoC.

PS4SocMemory

El UNB es lo que en Xbox One y Xbox One X se llama Crossbar Coherente porque es a partir del mismo en el que se hacen accesos a la memoria coherentes con la CPU. La GPU accede al UNB a través de dos buses distintos:  Onion y Onion+ que siguen dos caminos de datos diferentes para comunicarse con el UNB. Lo que no sabíamos era la forma en la que se comunicaba el Southbridge con el SoC principal de la consola, ahora lo sabemos, a través del IOC (In/Out Controller) que al mismo tiempo esta cableado a un elemento llamado HUB, dicho HUB habitualmente se encuentra dentro de la GPU y están conectados una serie de componentes que el SDK llama clientes DAGB. ¿Cuales son estos clientes?

DAGB

Y con ello nos encontramos con una sorpresa de entrada que es el llamado GPU DMA… ¿DMA en la GPU si se supone que hay un solo pozo de memoria y este se encuentra completamente unificado? Al menos es lo que los fanboys de Sony iban diciendo por ahí por activa y por pasiva… Hasta el punto de recibir ataques por mi parte y tener que ceder en ello frente a ciertos gurus enterados. ¿Os acordáis cuando muchos se llenaban la boca con el llamado hUMA? Solo hay que realizar una busqueda en Google para ver como en su día se dio por hecho. hUMA es a terminos prácticos la completa unificación en el direccionanamiento de memoria de tal manera que todos los accesos a la misma sean coherentes.

450_1000

Pero para que esto se produjese entonces el canal de acceso que es el MC -> GARLIC debería desaparecer y hacerse a través del Onion o una version mejorada del mismo. Que es lo que ocurre en el SoC AMD Carrizo precisamente que es para PC pero no ocurre ni en PS4 ni en PS4 Pro que tienen el uncore de su antecesor que es el AMD Kaveri. La unidad DMA se utiliza en este caso para acceder al UNB en el caso de que el MC este ocupado accediendo a memoria y no permita dicho camino de datos.

¿Cuando utilizaremos Onion o Garlic para la GPU? Dependiendo del espacio de memoria al que queramos acceder, obviamente el ancho de banda es dispar y resulta en un cuello de botella dependiendo de cada caso… Bueno, en realidad tanto PS4 como PS4 Pro tienen un enorme cuello de botella incluso utilizando el GARLIC como bus dado que los ROPS (CBDB en el SDK) pueden escribir 8 bytes por ciclo de reloj y tenemos 32 de ellos.

¿Os acordáis de esto?

Pues es aún peor realmente.

¿Donde esta el cuello de botella para empezar? En las cifras del «Load Only» que es solo lectura, esto es importante por el hecho de que en el camino de datos las texturas se leen desde la memoria principal.

La cantidad de ROPS/CBDB entre PS4 Pro y PS4 estándar es el mismo, pero la cantidad de unidades de texturas se ha duplicado al duplicarse las Compute Units dado que están dentro por lo que PS4 Pro tiene un cuello de botella importante en cuanto a la memoria… ¿Es por ello que Microsoft en Xbox One X ha colocado un bus de 384 bits? Lo que esta claro es que las causas de esto son el hecho de querer rebajar costes con la consola, pero las consecuencias es un enorme cuello de botella sobre la tasa de texturizado.

Pero la cosa no termina aquí… ¿Que ocurre cuando los clientes DAGB quieren acceder al bus GARLIC? Al fin y al cabo pueden acceder a ambos buses y no solo al Onion.

Es decir, si queremos el máximo rendimiento para la GPU, durante el renderizado de la escena los clientes DAGB no tocar… Esto me recuerda a que los DME/Move Engines en el caso de Xbox One son clientes DAGB… Aquí se puede prescindir de ellos pero en la consola de Microsoft son necesarios para el traslado de memoria de la DDR3 a la ESRAM. Os aviso que no es el único momento en que vais a ver el problema de la arquitectura de la Xbox One a través de PS4.

Por otro lado no creo que cualquiera con do dedos de frente se atreva a renderizar haciendo uso del bus Onion por su bajo ancho de banda, aparte que se ve compartido con los clientes DAGB.

Y la cosa empeora cuando el IOC entra en juego porque el Southbridge se ha de comunicar con la CPU.

Pero es que esto es la comunicación con el UNB, no con la memoria directamente y los tiempos de acceso y el ancho de banda se han de compartir con la CPU.

Dado que la CPU de PS4, PS4 Pro, Xbox One y Xbox One X son identicas y su acceso al UNB es el mismo en los cuatro sistemas de los datos de PS4 podemos extrapolar lo de Xbox One y Xbox One X.

¿Y que nos queda? El rendimiento combinado en acceso por parte de ONION (UNB)+GARLIC a la memoria principal en diferentes condiciones.

Como se puede ver el ancho de banda disponible para la GPU decrementa con el número de núcleos utilizados por la CPU. De cara a una siguiente generacion donde el ancho de banda utilizado por el Ryzen es superior… Al del Jaguar. En todo caso esto demuestra uno de los problemas de la memoria unificada que es la contención de memoria producida por el hecho de que esta tenga varios clientes al mismo tiempo.

Consecuencias sobre el Rendimiento Gráfico

¿Y que hay del rendimiento gráfico dependiendo del ancho de banda? El SDK es muy detallado sobre el tema, demasiado diría yo, pero mejor para nosotros.

La documentación nos dice:

  • Cuando el tamaño del triangulo es pequeño, el rendimiento de procesamiento de vertices del VGT de 1.6 GVtx/s es el cuello de botella. El VGT puede procesar un solo vertice por ciclo de reloj y hay dos en toda la GPU, así que la tasa es dos veces 800 Mhz, o 1.6 GVtx/s. A medida que el tamaño de los triangulos decrementa, el Pixel Shader se convirte en el cuello de botella.
  • Para el test de escritura, cuando los triangulos son grandes, el rendimiento de 25.6 GPixel/s es el cuello de botella. El rendimiento de un solo CB es de 4 pixels/ciclo de reloj, así que para unos 8 Color Buffer es de 25.6 Gpixeles/seg.
  • En el pasado, los tests de lectura/escritura y el test de rendimiento de lectura estabán limitados a los 19 GPixel/s debido a un problema con el número de SGPRs del usuario en el pixel shader. Esto era debido a que un gran número de SGPR. Sin embargo, este limite superior ha sido eliminado.

¿Que es el VGT? Se trata del rasterizador en el caso que nos ocupa tenemos dos de ellos por lo que puede rasterizar unos 2 triangulos por ciclo de reloj. Siendo el número de triangulos máximos que podrá enviar a las TMUs y los Pixel Shader de 1600 millones de triangulos/seg, recordad que 1 billón americano= 1000 millones europeos.

Veamos ahora el rendimiento con la PS4 Pro.

Y lo que no dice la documentación:

  • El número máximo de procesamiento de vertices en modo NEP es de 3.64 GVtx/s (4 Vtx/ciclo de reloj).
  • La tasa máxima de pixeles de salida es de 58 GPixel/s (64 pixel/ciclo de reloj), pero esto no fue obtenido por haber impactdo el limite superior del ancho de banda de la memoria.
  • El resultado cuando el tamño del triangulos grande es de 40 GPixel/s, o 160GB/s cuando lo convertimos en ancho de banda. La velocidad efectiva de las escrituras a memoria desde el CB esta sobre este nivel de rendimiento.

Esperad, esperad… Aquí me encuentro con la primera sorpresa del día… ¿64 Pixeles por ciclo de reloj en PS4 Pro? Esto tiene una explicación muy simple, la llamada Delta Color Compression.

¿En que consiste? Bueno, los ROPS lo que hacen es simplemente escribir en memoria por lo que podemos empaquetar varios búfers de imagen en un solo envio o varios pixeles y aumentar así el ancho de banda de manera artificial. Seguimos teniendo 32 ROPS/CDDB pero podemos enviar muchos más datos en un solo envio. ¿Lo malo con lo que se enfrenta PS4 PRo? Pues que el cuello de botella es importante y una máquina que puede transmitir 58 GPixels/s se queda solo en 40 GPixels/s de tasa de relleno por falta de ancho de banda. Es decir, la tasa de relleno de PS4 Pro no es 2X la de PS4.

El otro punto importante con la memoria es la cantidad de datos por triangulo/fragmento asociados, cuantas más coordenadas/atributos de texturas estén asociados más bajo será el rendimiento debido a la mayor necesidad de ancho de banda con la memoria.

El número entre parentesis es la cantidad de bytes que ocupan los atributos de manera acumulativa. La documentación nos aclara los números de la siguiente manera:

  • Cuando hay un número pequeño de triangulos y atributos, el rendimiento en cuanto a vertices es el cuello de botella.
  • A medida que el número de atributos aumenta, el ancho de banda se convierte en el cuello de botella. El número de datos que lee el VS se incrementa por lo que el ancho de banda de la memoria se satura.
  • Los atributos son leidos por el fetch shader. Se leen 4 bytes a la vez, por lo que el número de atributos no tiene efecto. Sin embargo la cantidad de datos leidos por un solo Vertex Shader y como estan alineados los datos afecta al rendimiento.

Ahora tened en cuenta que en el caso de Xbox One y Xbox One S tenemos una memoria de solo 68GB/s y…

Y no, estos datos no se leen precisamente de la ESRAM. Acabáis de descubrir porque la configuración de memoria de Xbox One y Xbox One S es una mierda hablando mal y claro. En fin, sigamos con PS4 Pro.

¿El motivo de estas cifras? El ancho de banda de la memoria de nuevo es el cuello de botella para la GPU de PS4 Pro. Si lo combinamos con los anchos de banda reales en diferentes circunstancias que se han visto arriba los problemas se agravan aún más y la cifra pasa a ser mucho más baja en cuanto a rendimiento.

Perfiles

Dado que es una GPU que tiene como origen el PC y por tanto esta pensada para los diferentes perfiles de Direct3D, esta tiene diferentes perfiles de funcionamiento en lo que el pipeline gráfico varia de una manera u otra al añadir más o menos etapas sobre el perfil principal. Cuanto más etapas hay en el pipeline gráfico peor será el rendimiento dado que la potencia de la GPU no aumenta, pero hay cosas que no se pueden hacer en los perfiles más rápidos. Dado que la GPU de Xbox One es de la misma naturaleza esto es directamente aplicable a la misma también.

Fijaos como las únicas etapas afectadas por el ancho de banda de la memoria son el Vertex Shader, Geometry Shader y Pixel Shader.

Y de nuevo veamos lo que dice el SDK:

  • No necesitas activar las etapas de Pixel Shader y Vertex Shader porque siempre están activas.
  • Con la excepción de la etapa de teselación, todas las etapas de función fija están siempre activas.
  • Pese  a que el Teselador es una etapa de función fija, puedes activarla y desactivarla.
  • Si tu título utiliza las etapas de geometria o teselación del pipeline lógica, tienes que activar las etapas correspondientes del pipeline del hardware. Tienes que entender el mapeado de las etapas lógicas de los shaders para activarlos, compilar los shaders para la etapa de los shaders acecuada y atar los shaders compilados a sus etapas de apropiadas del hardware.

Y más adelante no da una tabla de los diferentes modos.

A partir de aquí podemos deducir cual sería el camino de datos, esto no es más que los perfiles de Direct3D.

Compute Shaders

Mientras que cada tipo de shader solo puede correr en su parte correspondiente del pipeline, los Compute Shaders pueden hacerlo en cualquier momento y bajo cualquier perfil. Esto es al contrario que en el Direct3D de Xbox donde los perfiles de D3D9 y D3D10 no tienen acceso a los Compute Shaders.

Esto es sumamente interesante, porque podemos manipular a través del Compute Shader cualquier resultado previo, al fin y al cabo todos corren en la misma unidad pero esto significa que se puede ir intercalando entre el pipeline de computación y el pipeline gráfico.