Estructuras de datos clave y sus roles en RenderingNG

Chris Harrelson
Chris Harrelson
Daniel Cheng
Daniel Cheng
Philip Rogers
Philip Rogers
Koji Ishi
Koji Ishi
Ian Kilpatrick
Ian Kilpatrick
Kyle Charbonneau
Kyle Charbonneau

En las publicaciones anteriores de esta serie, se proporcionaba una descripción general de los objetivos, las propiedades clave y las piezas de componentes de alto nivel de la arquitectura de RenderingNG. Ahora, profundicemos en las estructuras de datos clave que son entradas y salidas de la canalización de renderización.

Estas estructuras de datos son:

  • Los árboles de marcos, que constan de nodos locales y remotos que representan qué documentos web se encuentran en qué proceso de renderización y qué procesador de Blink.
  • El árbol de fragmentos inmutable representa el resultado (y la entrada) del algoritmo de restricción de diseño.
  • Árboles de propiedades, que representan las jerarquías de transformación, recorte, efecto y desplazamiento de un documento web, y se usan en toda la canalización.
  • Las listas de visualización y fragmentos de pintura son las entradas de los algoritmos de trama y capas.
  • Los marcos de compositor encapsulan las superficies, las superficies de renderización y los mosaicos de texturas de la GPU que se usan para dibujar con la GPU.

Antes de revisar estas estructuras de datos, quiero mostrar el siguiente ejemplo sencillo de lo que se basa en una de la publicación anterior. Usaré este ejemplo algunas veces en esta publicación, mostraré cómo se aplican las estructuras de datos.

<html>
  <div style="overflow: hidden; width: 100px; height: 100px;">
    <iframe style="filter: blur(3px);
      transform: rotateZ(1deg);
      width: 100px; height: 300px"
      id="one" src="foo.com/etc"></iframe>
  </div>
  <iframe style="top:200px;
    transform: scale(1.1) translateX(200px)"
    id="two" src="bar.com"></iframe>
</html>

Enmarcar árboles

A veces, Chrome puede elegir renderizar un marco de origen cruzado en un proceso de renderización diferente al del marco superior.

En el ejemplo de la introducción, hay tres marcos totales:

Un marco superior foo.com, que contiene dos iframes.

Con el aislamiento de sitios, Chromium usará dos procesos de procesamiento para renderizar esta página web. Cada proceso de renderización tiene su propia representación del árbol de marcos para esa página web:

Dos árboles de marcos que representan los dos procesos de renderización.

Un fotograma renderizado en un proceso diferente se representa como un fotograma remoto. Un marco remoto contiene la información mínima necesaria para actuar como marcador de posición en la renderización, como sus dimensiones, por ejemplo. De lo contrario, el marco remoto no contendrá la información necesaria para renderizar su contenido real.

Por el contrario, un marco local representa un fotograma que pasará por la canalización de renderización estándar descrita en publicaciones anteriores. El marco local contiene toda la información necesaria para convertir los datos de ese marco (como el árbol del DOM y los datos de estilo) en algo que se puede renderizar y mostrar.

La canalización de renderización opera con el nivel de detalle de un fragmento de árbol de marcos local. Considera un ejemplo más complicado con foo.com como fotograma principal:

<iframe src="bar.com"></iframe>

Y el siguiente submarco bar.com:

<iframe src="foo.com/etc"></iframe>

Aunque todavía hay solo dos procesadores, ahora hay tres fragmentos de árbol de marcos locales, con dos en el proceso de renderización de foo.com y uno en el de bar.com:

Una representación de las dos renderizaciones y tres fragmentos de árbol de marcos.

A fin de producir un marco del compositor para la página web, Viz solicita simultáneamente un marco del compositor al marco raíz de cada uno de los tres árboles de marcos locales y, luego, los agrega. (Consulta también la sección de marcos del compositor más adelante en esta entrada).

El marco principal foo.com y el submarco foo.com/other-page forman parte del mismo árbol de marcos y se renderizan en el mismo proceso. Sin embargo, los dos marcos siguen teniendo ciclos de vida de documentos independientes, ya que forman parte de diferentes fragmentos de árbol de marcos locales. Por este motivo, no es posible generar un fotograma del compositor para ambos en una sola actualización. El proceso de renderización no tiene suficiente información para componer el marco del compositor generado para foo.com/other-page directamente en el marco del compositor para el fotograma principal foo.com. Por ejemplo, el marco superior bar.com fuera del proceso puede afectar la visualización del iframe foo.com/other-url, ya que transforma el iframe con CSS o bien oculta partes del iframe con otros elementos de su DOM.

Cascada de actualización de propiedades visuales

Las propiedades visuales, como el factor de escala del dispositivo y el tamaño del viewport, afectan el resultado renderizado y deben sincronizarse entre los fragmentos de árbol de marcos locales. La raíz de cada fragmento de árbol de marcos local tiene un objeto de widget asociado. Las actualizaciones de propiedades visuales van al widget del marco principal antes de propagarse a los widgets restantes de arriba abajo. Por ejemplo, cuando cambia el tamaño del viewport:

Diagrama del proceso explicado en el texto anterior.

Este proceso no es instantáneo, por lo que las propiedades visuales replicadas también incluyen un token de sincronización. El compositor de Viz usa este token de sincronización para esperar a que todos los fragmentos de árbol de marcos locales envíen una trama del compositor con el token de sincronización actual. Este proceso evita mezclar los fotogramas del compositor con diferentes propiedades visuales.

El árbol de fragmentos inmutable

El árbol de fragmentos inmutable es el resultado de la etapa de diseño de la canalización de renderización. Representa la posición y el tamaño de todos los elementos en la página (sin transformaciones aplicadas).

Representación de los fragmentos en cada árbol, con un fragmento marcado como que necesita diseño.

Cada fragmento representa una parte de un elemento del DOM. Por lo general, solo hay un fragmento por elemento, pero puede haber más si se divide en diferentes páginas cuando se imprimen o en columnas cuando se usa en un contexto de varias columnas.

Después del diseño, cada fragmento se vuelve inmutable y nunca se vuelve a cambiar. Es importante destacar que también aplicamos algunas restricciones adicionales. No:

  • Permite cualquier referencia "arriba" en el árbol. (Un elemento secundario no puede tener un puntero hacia su elemento superior).
  • datos en “burbuja” hacia abajo en el árbol (un elemento secundario solo lee información de sus elementos secundarios, no de su elemento superior).

Estas restricciones nos permiten reutilizar un fragmento para un diseño posterior. Sin estas restricciones, a menudo, necesitaremos volver a generar el árbol completo, lo cual es costoso.

La mayoría de los diseños suelen ser actualizaciones incrementales. Por ejemplo, una app web actualiza una pequeña parte de la IU cuando el usuario hace clic en un elemento. Idealmente, el diseño debería funcionar de manera proporcional a lo que realmente cambió en la pantalla. Para lograrlo, podemos reutilizar tantas partes del árbol anterior como sea posible. Esto significa (por lo general) que solo necesitamos reconstruir la columna vertebral del árbol.

En el futuro, este diseño inmutable nos permitirá hacer cosas interesantes, como pasar el árbol de fragmentos inmutable por los límites de los subprocesos, si es necesario (para realizar fases posteriores en un subproceso diferente), generar varios árboles para una animación de diseño fluida o realizar diseños especulativos paralelos. Además, nos da el potencial del diseño multiproceso.

Elementos de fragmentos intercalados

El contenido intercalado (predominantemente texto con estilo) usa una representación ligeramente diferente. En lugar de una estructura de árbol con cuadros y punteros, representamos el contenido intercalado en una lista plana que representa el árbol. El beneficio principal es que una representación de lista plana para intercalados es rápida y útil a la hora de inspeccionar o consultar estructuras de datos intercaladas, y es eficiente en términos de memoria. Esto es muy importante para el rendimiento del procesamiento web, ya que la renderización de texto es muy compleja y puede convertirse con facilidad en la parte más lenta de la canalización, a menos que esté altamente optimizada.

Como nota histórica interesante, esto es muy similar a cómo Internet Explorer representaba anteriormente su DOM, ya que se compilaba en un principio de manera similar a un editor de texto.

La lista plana se crea para cada contexto de formato intercalado, en el orden de una búsqueda con prioridad en la profundidad de su subárbol de diseño intercalado. Cada entrada en la lista es una tupla de (objeto, número de elementos subordinados). Por ejemplo, considera el siguiente DOM:

<div style="width: 0;">
  <span style="color: blue; position: relative;">Hi</span> <b>there</b>.
</div>

(Ten en cuenta que la propiedad width se establece en 0 para que la línea se ajuste entre "Hi" y "there"). Cuando el contexto de formato intercalado para esta situación se representa como un árbol, se verá de la siguiente manera:

{
  "Line box": {
    "Box <span>": {
      "Text": "Hi"
    }
  },
  "Line box": {
    "Box <b>": {
      "Text": "There"
    }
  },
  {
    "Text": "."
  }
}

La lista plana se ve de la siguiente manera:

  • (Cuadro de línea, 2)
  • (Casilla <span>, 1)
  • (Texto "Hi", 0)
  • (Cuadro de línea, 3)
  • (Casilla <b>, 1)
  • (Texto "there", 0)
  • (Texto ".", 0)

Hay muchos consumidores de esta estructura de datos: APIs de accesibilidad y APIs de geometría, como getClientRects y contenteditable. Cada uno tiene requisitos diferentes. Estos componentes acceden a la estructura plana de datos a través de un cursor de conveniencia.

El cursor tiene APIs como MoveToNext, MoveToNextLine y CursorForChildren. Esta representación del cursor es muy eficaz para el contenido de texto por varios motivos:

  • La iteración en el orden de búsqueda en profundidad es muy rápida. Se usa muy a menudo porque es similar a los movimientos de signo de intercalación. Como se trata de una lista plana, la búsqueda centrada en la profundidad solo aumenta el desplazamiento del array, lo que proporciona iteraciones rápidas y localidad de memoria.
  • Proporciona una búsqueda centrada en la amplitud, que es necesaria, por ejemplo, cuando se pinta el fondo de líneas y cuadros intercalados.
  • Conocer la cantidad de elementos subordinados hace que avanzar al siguiente elemento del mismo nivel sea rápido (solo incrementa el desplazamiento del array en ese número).

Árboles de propiedades

Como sabes, el DOM es un árbol de elementos (más nodos de texto), y CSS puede aplicar varios estilos a los elementos.

En su mayoría, tienen cuatro sabores de efecto:

  • Diseño: Entradas al algoritmo de restricción de diseño
  • Paint: Indica cómo pintar y tramar el elemento (pero no sus elementos subordinados).
  • Imagen: Efectos de trama o de dibujo aplicados al subárbol del DOM, como transformaciones, filtros y recortes.
  • Scrolling: Recorte y desplazamiento alineados con ejes y esquinas redondeadas del subárbol contenido.

Los árboles de propiedades son estructuras de datos que explican cómo se aplican los efectos visuales y de desplazamiento a los elementos del DOM. Estos proporcionan los medios para responder preguntas como las siguientes: dónde, en relación con la pantalla, se encuentra un elemento del DOM determinado, según su tamaño y posición de diseño. ¿Qué secuencia de operaciones de GPU debería usarse para aplicar efectos visuales y de desplazamiento?

Los efectos visuales y de desplazamiento en la Web son muy complicados en todo su esplendor. Por lo tanto, lo más importante que hacen los árboles de propiedades es traducir esa complejidad en una sola estructura de datos que representa con precisión su estructura y significado, a la vez que quita el resto de la complejidad del DOM y CSS. Esto nos permite implementar algoritmos de composición y desplazamiento con mucha más confianza. En particular, considera lo siguiente:

  • La geometría potencialmente propensa a errores y otros cálculos se pueden centralizar en un solo lugar.
  • La complejidad de compilar y actualizar árboles de propiedades se aísla en una etapa de canalización de renderización.
  • Es mucho más fácil y rápido enviar árboles de propiedades a diferentes subprocesos y procesos que con un estado completo del DOM, lo que permite su uso en muchos casos de uso.
  • Cuantos más casos de uso haya, más ventajas obtendremos del almacenamiento en caché de geometría compilado en la parte superior, ya que pueden reutilizar las cachés de cada una.

RenderingNG usa árboles de propiedades para muchos propósitos, incluidos los siguientes:

  • Separa la composición de la pintura y la composición del subproceso principal.
  • Determinar una estrategia óptima de composición o dibujo
  • Se mide la geometría de IntersectionObserver.
  • Evitar el trabajo para elementos fuera de pantalla y mosaicos de textura de la GPU
  • Invalida, de forma eficiente y precisa, pintura y trama.
  • Se mide el cambio de diseño y el Largest Contentful Paint en las Métricas web esenciales.

Cada documento web tiene cuatro árboles de propiedades separados: transformación, recorte, efecto y desplazamiento.(*) El árbol de transformaciones representa las transformaciones y el desplazamiento de CSS. (Una transformación de desplazamiento se representa como una matriz de transformación 2D). El árbol de recortes representa los clips de desbordamiento. El árbol de efectos representa todos los demás efectos visuales: opacidad, filtros, máscaras, modos de combinación y otros tipos de clips, como la ruta de recorte. El árbol de desplazamientos representa información sobre el desplazamiento, por ejemplo, cómo se encadenan los desplazamientos. Es necesario para realizar el desplazamiento en el subproceso del compositor. Cada nodo en un árbol de propiedades representa un efecto visual o de desplazamiento aplicado por un elemento del DOM. Si tiene varios efectos, puede haber más de un nodo del árbol de propiedades en cada árbol del mismo elemento.

La topología de cada árbol es como una representación dispersa del DOM. Por ejemplo, si hay tres elementos del DOM con clips de desbordamiento, habrá tres nodos de árbol de recorte, y la estructura del árbol de recorte seguirá la relación de bloque contenedor entre los clips de desbordamiento. También hay enlaces entre los árboles. Estos vínculos indican la jerarquía relativa del DOM y, por lo tanto, el orden de aplicación de los nodos. Por ejemplo, si una transformación en un elemento del DOM se encuentra debajo de otro elemento del DOM con un filtro, entonces, por supuesto, la transformación se aplica antes que el filtro.

Cada elemento del DOM tiene un estado del árbol de propiedades, que es una tupla de 4 elementos (transformación, recorte, efecto, desplazamiento) que indica los nodos de recorte del principal, transformación y árbol de efectos más cercanos que se aplican a ese elemento. Esto es muy conveniente, ya que con esta información sabemos exactamente la lista de clips, transformaciones y efectos que se aplican a ese elemento, y en qué orden. Esto nos indica dónde está en la pantalla y cómo dibujarla.

Ejemplo

(fuente).

<html>
  <div style="overflow: scroll; width: 100px; height: 100px;">
    <iframe style="filter: blur(3px);
      transform: rotateZ(1deg);
      width: 100px; height: 300px"
  id="one" srcdoc="iframe one"></iframe>
  </div>
  <iframe style="top:200px;
      transform: scale(1.1) translateX(200px)" id=two
      srcdoc="iframe two"></iframe>
</html>

En el ejemplo anterior (que es ligeramente diferente al de la introducción), estos son los elementos clave de los árboles de propiedades generados:

Un ejemplo de los distintos elementos del árbol de propiedades.

Muestra listas y bloques de pintura

Un elemento de visualización contiene comandos de dibujo de bajo nivel (consulta aquí) que se pueden rasterizar con Skia. Los elementos de visualización suelen ser simples, con solo algunos comandos de dibujo, como dibujar un borde o un fondo. El recorrido del árbol de pintura itera sobre el árbol de diseño y los fragmentos asociados siguiendo el orden de pintura de CSS para producir una lista de elementos de visualización.

Por ejemplo:

Un cuadro azul con las palabras “Hello World” dentro de un rectángulo verde.

<div id="green" style="background:green; width:80px;">
    Hello world
</div>
<div id="blue" style="width:100px;
  height:100px; background:blue;
  position:absolute;
  top:0; left:0; z-index:-1;">
</div>

Este código HTML y CSS produciría la siguiente lista de visualización, en la que cada celda es un elemento de visualización:

Fondo de la vista Fondo de #blue Fondo de #green Texto intercalado de #green
drawRect de tamaño 800 × 600 y color blanco. drawRect con un tamaño de 100 x 100 en la posición 0,0 y color azul. drawRect con tamaño de 80 × 18 en la posición 8,8 y color verde. drawTextBlob con la posición 8 y 8,y el texto "Hello world".

La lista de elementos de visualización se ordena de atrás hacia adelante. En el ejemplo anterior, el div verde está antes del div azul en el orden del DOM, pero el orden de pintura de CSS requiere que el div azul con índice z negativo se pinte antes (paso 3) del div verde (paso 4.1). Los elementos de visualización se corresponden, a grandes rasgos, con los pasos atómicos de la especificación del orden de pintura de CSS. Un solo elemento del DOM puede generar varios elementos de visualización, como el hecho de que #green tiene un elemento de visualización para el fondo y otro para el texto intercalado. Este nivel de detalle es importante para representar la complejidad completa de la especificación del orden de pintura de CSS, como el intercalado creado por el margen negativo:

Un rectángulo verde con un cuadro gris parcialmente superpuesto y las palabras &quot;Hello World&quot;.

<div id="green" style="background:green; width:80px;">
    Hello world
</div>
<div id="gray" style="width:35px; height:20px;
  background:gray;margin-top:-10px;"></div>

De esta manera, se generaría la siguiente lista de visualización, en la que cada celda es un elemento visible:

Fondo de la vista Fondo de #green Fondo de #gray Texto intercalado de #green
drawRect de tamaño 800 × 600 y color blanco. drawRect con tamaño de 80 × 18 en la posición 8,8 y color verde. drawRect con tamaño de 35 x 20 en la posición 8,16 y color gris. drawTextBlob con la posición 8 y 8,y el texto "Hello world".

La lista de artículos de visualización se almacena y se vuelve a usar en actualizaciones posteriores. Si un objeto de diseño no cambió durante el recorrido del árbol de pintura, sus elementos de visualización se copian de la lista anterior. Una optimización adicional se basa en una propiedad de la especificación del orden de pintura de CSS: la pila de contextos se pinta de forma atómica. Si no se modificó ningún objeto de diseño dentro de un contexto de apilado, el recorrido del árbol de pintura omite el contexto de apilado y copia la secuencia completa de elementos de visualización de la lista anterior.

El estado actual del árbol de propiedad se mantiene durante el recorrido del árbol de la pintura, y la lista de elementos de visualización se agrupa en "fragmentos" de elementos de visualización que comparten el mismo estado del árbol de propiedad. Esto se demuestra en el siguiente ejemplo:

Un cuadro rosa con un recuadro naranja inclinado.

<div id="scroll" style="background:pink; width:100px;
   height:100px; overflow:scroll;
   position:absolute; top:0; left:0;">
    Hello world
    <div id="orange" style="width:75px; height:200px;
      background:orange; transform:rotateZ(25deg);">
        I'm falling
    </div>
</div>

De esta manera, se generaría la siguiente lista de visualización, en la que cada celda es un elemento visible:

Fondo de la vista Fondo de #scroll Texto intercalado de #scroll Fondo de #orange Texto intercalado de #orange
drawRect de tamaño 800 × 600 y color blanco. drawRect con un tamaño de 100 x 100 en la posición 0,0 y color rosa. drawTextBlob con la posición 0,0 y el texto "Hello world". drawRect con tamaño 75 x 200 en la posición 0,0 y color naranja. drawTextBlob con la posición 0,0 y el texto "I'm cayendo"

El árbol de propiedad de transformación y los fragmentos de pintura serían los siguientes:

Una imagen de la tabla anterior, las dos primeras celdas en el bloque 1, la tercera en el bloque 2 y las dos últimas celdas en el bloque 3.

La lista ordenada de fragmentos de pintura, que son grupos de elementos de visualización y un estado del árbol de propiedades, son las entradas del paso de adaptación de capas de la canalización de renderización. Toda la lista de fragmentos de pintura se podría combinar en una sola capa compuesta y rasterizarse en conjunto, pero esto requeriría una rasterización costosa cada vez que el usuario se desplazaba. Se podía crear una capa compuesta para cada fragmento de pintura y se podría rasterizar de forma individual para evitar toda la rerasterización, pero eso agotaría rápidamente la memoria de la GPU. El paso de creación de capas tiene que hacer concesiones entre la memoria de la GPU y reducir los costos cuando las cosas cambian. Un buen enfoque general es combinar fragmentos de forma predeterminada y no combinar fragmentos de pintura que tengan estados de árbol de propiedad que se espera que cambien en el subproceso del compositor, como el desplazamiento del subproceso de compositor o las animaciones de transformación de subproceso del compositor.

Lo ideal sería que, en el ejemplo anterior, se produzcan dos capas compuestas:

  • Una capa compuesta de 800 x 600 que contiene los comandos de dibujo:
    1. drawRect con un tamaño de 800 × 600 y color blanco
    2. drawRect con un tamaño de 100 x 100 en la posición 0,0 y color rosa
  • Una capa compuesta de 144 x 224 que contiene los comandos de dibujo:
    1. drawTextBlob con la posición 0,0 y el texto "Hello World"
    2. traducir 0,18
    3. rotateZ(25deg)
    4. drawRect con tamaño 75 x 200 en la posición 0,0 y color naranja
    5. drawTextBlob con la posición 0,0 y el texto "Estoy cayendo"

Si el usuario se desplaza por #scroll, se mueve la segunda capa compuesta, pero no se necesita rasterización.

En el ejemplo que aparece aquí, de la sección anterior sobre árboles de propiedades, hay seis fragmentos de pintura. Junto con sus estados del árbol de propiedades (transformación, recorte, efecto, desplazamiento), son los siguientes:

  • Fondo del documento: desplazamiento del documento, recorte del documento, raíz, desplazamiento del documento
  • Esquina horizontal, vertical y de desplazamiento para div (tres fragmentos de pintura separados): desplazamiento de documento, clip de documento, desenfoque #one y desplazamiento de documento.
  • Iframe #one: #one, rotación, clip de desplazamiento ampliado, #one desenfoque, desplazamiento div.
  • Iframe #two: escala #two, clip de documento, raíz, desplazamiento del documento.

Fotogramas del compositor: superficies, superficies de renderización y mosaicos de texturas de GPU

Como se describió en la entrada anterior (puedes ver un ejemplo trabajado aquí), los procesos de renderización y navegador administran la rasterización del contenido y, luego, envían los fotogramas del compositor al proceso de Viz para presentarlos en la pantalla. Los fotogramas del compositor son la forma en la que RenderingNG representa la forma de unir contenido rasterizado y dibujarlo de manera eficiente con la GPU.

Tarjetas

En teoría, un proceso de renderización o un compositor de procesos de navegador podrían rasterizar píxeles en una sola textura del tamaño completo del viewport del procesador y enviar esa textura a Viz. Para mostrarla, el compositor de pantalla solo tendría que copiar los píxeles de esa textura única en la posición adecuada en el búfer de fotogramas (por ejemplo, la pantalla). Sin embargo, si el compositor quisiera actualizar incluso un solo píxel, necesitaría volver a rasterizar todo el viewport y enviar una textura nueva a Viz.

En cambio, el viewport se divide en mosaicos. Un mosaico de textura de GPU independiente respalda cada mosaico con los píxeles rasterizados para parte del viewport. Luego, el procesador puede actualizar tarjetas individuales o incluso cambiar la posición en la pantalla para las tarjetas existentes. Por ejemplo, cuando se desplaza por un sitio web, la posición de las tarjetas existentes cambiaría hacia arriba y, solo ocasionalmente, se debería rasterizar una tarjeta nueva para el contenido que se encuentra más abajo en la página.

Cuatro mosaicos.

La imagen de arriba muestra una imagen de un día soleado con cuatro mosaicos. Cuando se produce un desplazamiento, comienza a aparecer un quinto mosaico. Uno de los mosaicos tiene un solo color (celeste), y hay un video y un iframe en la parte superior. Esto nos lleva al siguiente tema.

Cuadrículas y superficies

Los mosaicos de texturas de GPU son un tipo especial de cuatro, que es solo un nombre elegante para una categoría de textura u otra. Un cuadrante identifica la textura de entrada y también indica cómo transformarla y aplicarle efectos visuales. Por ejemplo, los mosaicos de contenido normal tienen una transformación que indica su posición x e y en la cuadrícula de mosaicos.

Mosaicos de texturas de GPU.

Estos mosaicos rasterizados se unen en un pase de renderización, que es una lista de cuadrantes. El pase de renderización no contiene información de píxeles; en su lugar, tiene instrucciones sobre dónde y cómo dibujar cada cuadrante para producir el resultado de píxeles deseado. Hay un cuatro de dibujo para cada mosaico de textura de la GPU. El compositor de pantalla solo debe iterar a través de la lista de cuadrantes y dibujar cada uno con los efectos visuales especificados para producir el resultado de píxeles deseado para el pase de renderización. La composición de cuadrantes de dibujo para un pase de renderización se puede realizar de manera eficiente en la GPU, ya que los efectos visuales permitidos se eligen cuidadosamente para que sean aquellos que se asignan directamente a las funciones de GPU.

Existen otros tipos de cuadrantes de dibujo que van más allá de los mosaicos rasterizados. Por ejemplo, hay cuatrigramas de dibujo de colores sólidos que no están respaldados por ninguna textura, o cuadrados de dibujo de texturas para texturas que no son de mosaicos, como videos o lienzos.

También es posible que un fotograma del compositor incorpore otro fotograma del compositor. Por ejemplo, el compositor del navegador produce un marco del compositor con la IU del navegador y un rectángulo vacío en el que se incorporará el contenido del compositor de renderización. Otro ejemplo son los iframes aislados del sitio. Esta incorporación se realiza a través de plataformas.

Cuando un compositor envía un fotograma del compositor, va acompañado de un identificador, denominado ID de superficie, que permite que otros marcos del compositor lo incorporen como referencia. Viz almacena el fotograma del compositor más reciente que se envía con un ID de superficie particular. Luego, otro fotograma del compositor puede hacer referencia a él con un cuatro de dibujo de superficie y, por lo tanto, Viz sabe qué dibujar. (ten en cuenta que los cuatriciclos de dibujo de superficie solo contienen IDs de superficie, no texturas).

Pases de renderización intermedios

Algunos efectos visuales, como muchos filtros o modos de combinación avanzados, requieren que se dibujen dos o más cuadrantes en una textura intermedia. Luego, la textura intermedia se dibuja en un búfer de destino en la GPU (o posiblemente otra textura intermedia) y aplica el efecto visual al mismo tiempo. Para permitirlo, un fotograma del compositor contiene una lista de pases de renderización. Siempre hay un pase de renderización raíz, que se dibuja en último lugar y cuyo destino corresponde al búfer de fotogramas, y puede haber más.

La posibilidad de varios pases de renderización explica el nombre “pase de renderización”. Cada pase debe ejecutarse de forma secuencial en la GPU, en varios “pases”, mientras que un solo pase se puede completar en un solo cálculo de GPU masivo paralelo.

Agregación

Se envían varios fotogramas del compositor a Viz y deben dibujarse juntos en la pantalla. Esto se logra mediante una fase de agregación que los convierte en un solo marco agregado del compositor. La agregación reemplaza los cuadrantes de dibujo de superficie por los fotogramas del compositor que especifican. También es una oportunidad para optimizar las texturas intermedias innecesarias o el contenido fuera de pantalla. Por ejemplo, en muchos casos, el marco del compositor para un iframe aislado de sitio no necesita su propia textura intermedia y se puede dibujar directamente en el búfer del fotograma con los cuadrantes de dibujo adecuados. La fase de agregación determina esas optimizaciones y las aplica en función del conocimiento global al que no pueden acceder los compositores de renderización individuales.

Ejemplo

Estos son los fotogramas del compositor reales que representan el ejemplo del principio de esta publicación.

  • Plataforma de foo.com/index.html: id=0
    • Pase de renderización 0: Dibujo en el resultado.
      • Pase de renderización cuadrante: dibuja con un desenfoque de 3 px y recorte en el pase de renderización 0
        • Pase de renderización 1:
          • Dibuja cuadras para el contenido de mosaicos del iframe #one, con posiciones x e y para cada uno.
      • Cuadrícula de dibujo de superficie: con ID 2, dibujada con escala y transformación “traducir”.
  • Superficie de la IU del navegador: ID=1
    • Pase de renderización 0: Dibujo en el resultado.
      • Dibuja cuadras para la IU del navegador (también en mosaico)
  • Plataforma de bar.com/index.html: ID=2
    • Pase de renderización 0: Dibujo en el resultado.
      • Dibuja cuadras para el contenido del iframe #two, con posiciones x e y para cada uno.

Conclusión

¡Gracias por leer esta información! Junto con las dos publicaciones anteriores, concluye la descripción general de RenderingNG. A continuación, analizaremos en detalle los desafíos y la tecnología de muchos de los subcomponentes de la canalización de renderización, de principio a fin. Estarán disponibles pronto.

Ilustraciones de Una Kravets.