Examinons les principales structures de données, qui sont les entrées et les sorties du pipeline de rendu.
Ces structures de données sont:
- Les arborescences de cadres sont composées de nœuds locaux et distants qui représentent les documents Web dans quel processus de rendu et quel moteur de rendu Blink.
- L'arborescence de fragments immuable représente la sortie (et l'entrée) de l'algorithme de contrainte de mise en page.
- Les arborescences de propriétés représentent les hiérarchies de transformation, de découpage, d'effet et de défilement d'un document Web. Ils sont utilisés tout au long du pipeline.
- Les listes d'affichage et les blocs de peinture sont les entrées des algorithmes de rastérisation et de stratification.
- Les cadres du compositeur encapsulent les surfaces, les surfaces de rendu et les tuiles de texture GPU utilisées pour dessiner à l'aide du GPU.
Avant d'examiner ces structures de données, l'exemple suivant s'appuie sur un exemple de l'examen de l'architecture. Cet exemple est utilisé tout au long de ce document avec des démonstrations de la façon dont les structures de données s'y appliquent.
<!-- Example code -->
<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>
Arbres en forme de cadre
Chrome peut parfois choisir d'afficher un frame multi-origine dans un processus d'affichage différent de celui de son frame parent.
Dans l'exemple de code, il y a trois frames au total:
Avec l'isolation de sites, Chromium utilise deux processus d'affichage pour afficher cette page Web. Chaque processus de rendu possède sa propre représentation de l'arborescence des frames de cette page Web:
Un frame affiché dans un autre processus est représenté sous la forme d'un frame distant. Un frame distant contient les informations minimales requises pour servir d'espace réservé lors du rendu, telles que ses dimensions. Sinon, le frame distant ne contient aucune information nécessaire pour afficher son contenu réel.
À l'inverse, un frame local représente un frame qui passe par le pipeline de rendu standard. Le frame local contient toutes les informations nécessaires pour transformer les données de ce frame (telles que l'arborescence DOM et les données de style) en éléments pouvant être affichés.
Le pipeline de rendu opère sur la précision d'un fragment d'arborescence de frames locaux.
Prenons un exemple plus complexe avec foo.com
comme frame principal:
<iframe src="bar.com"></iframe>
Et la sous-fframe bar.com
suivante:
<iframe src="foo.com/etc"></iframe>
Bien qu'il n'y ait toujours que deux moteurs de rendu, il existe désormais trois fragments d'arborescence de frames locaux, dont deux dans le processus de rendu pour foo.com
et un dans le processus de rendu pour bar.com
:
Pour produire un frame de composition pour la page Web, Viz demande simultanément un frame de composition à partir du frame racine de chacun des trois arbres de frame locaux, puis les agrée. Reportez-vous également à la section Cadres compositeurs.
Le frame principal foo.com
et le sous-cadre foo.com/other-page
font partie du même arbre de frame et sont affichés dans le même processus.
Toutefois, les deux frames ont toujours des cycles de vie de document indépendants, car ils font partie de différents fragments d'arborescence de frame locaux.
Pour cette raison, il est impossible de générer une image de compositeur pour les deux en une seule mise à jour.
Le processus de rendu ne dispose pas de suffisamment d'informations pour combiner le cadre du compositeur généré pour foo.com/other-page
directement dans le cadre du compositeur du cadre principal foo.com
.
Par exemple, le frame parent bar.com
hors processus peut affecter l'affichage de l'iFrame foo.com/other-url
en transformant l'iFrame avec CSS ou en masquant des parties de l'iFrame avec d'autres éléments de son DOM.
Cascade de mises à jour visuelles des établissements
Les propriétés visuelles telles que le facteur de mise à l'échelle de l'appareil et la taille de la fenêtre d'affichage affectent la sortie affichée et doivent être synchronisées entre les fragments d'arborescence de frame locaux. La racine de chaque fragment d'arborescence de frames locaux est associée à un objet widget. Les mises à jour de la propriété visuelle sont transmises au widget du frame principal avant de se propager aux autres widgets de haut en bas.
Par exemple, lorsque la taille de la fenêtre d'affichage change:
Ce processus n'est pas instantané. Par conséquent, les propriétés visuelles répliquées incluent également un jeton de synchronisation. Le compositeur Viz utilise ce jeton de synchronisation pour attendre que tous les fragments d'arborescence de frame locaux envoient un frame de compositeur avec le jeton de synchronisation actuel. Ce processus évite de mélanger les cadres du compositeur avec des propriétés visuelles différentes.
Arborescence des fragments immuables
L'arborescence de fragments immuables est le résultat de l'étape de mise en page du pipeline de rendu. Il représente la position et la taille de tous les éléments de la page (sans transformation appliquée).
Chaque fragment représente une partie d'un élément DOM. En règle générale, il n'y a qu'un seul fragment par élément, mais il peut y en avoir d'autres s'il est réparti sur différentes pages lors de l'impression ou sur différentes colonnes dans un contexte multicolonne.
Après la mise en page, chaque fragment devient immuable et ne change plus jamais. Il est important de noter que nous appliquons également quelques restrictions supplémentaires. Ce que nous ne faisons pas:
- Autorisez toutes les références "haut" dans l'arborescence. (Un enfant ne peut pas avoir de pointeur vers son parent.)
- "bulle" les données dans l'arborescence (un enfant ne lit que les informations de ses enfants, pas de son parent).
Ces restrictions nous permettent de réutiliser un fragment pour une mise en page ultérieure. Sans ces restrictions, nous devrions souvent régénérer l'ensemble de l'arborescence, ce qui est coûteux.
La plupart des mises en page sont généralement des mises à jour incrémentielles. Par exemple, une application Web met à jour une petite partie de l'UI en réponse au clic de l'utilisateur sur un élément. Idéalement, la mise en page ne doit effectuer que des tâches proportionnelles à ce qui a réellement changé à l'écran. Pour ce faire, nous devons réutiliser autant de parties de l'arbre précédent que possible. Cela signifie que nous n'avons généralement besoin que de reconstruire la colonne vertébrale de l'arborescence.
À l'avenir, cette conception immuable pourrait nous permettre de faire des choses intéressantes, comme transmettre l'arborescence de fragments immuables au-delà des limites de thread si nécessaire (pour effectuer des phases ultérieures sur un thread différent), générer plusieurs arborescences pour une animation de mise en page fluide ou effectuer des mises en page spéculatives parallèles. Cela nous donne également le potentiel de la mise en page multithread elle-même.
Éléments de fragment intégrés
Le contenu intégré (principalement le texte avec style) utilise une représentation légèrement différente. Au lieu d'une structure arborescente avec des cases et des pointeurs, nous représentons le contenu intégré dans une liste plate représentant l'arborescence. L'avantage principal est qu'une représentation de liste plate pour les éléments intégrés est rapide, utile pour inspecter ou interroger des structures de données intégrées, et efficace en termes de mémoire. Cela est extrêmement important pour les performances de rendu Web, car le rendu du texte est très complexe et peut facilement devenir la partie la plus lente du pipeline, sauf s'il est très optimisé.
La liste plate est créée pour chaque contexte de mise en forme intégrée dans l'ordre d'une recherche axée sur la profondeur dans sa sous-arborescence de mise en page intégrée. Chaque entrée de la liste est un tuple (objet, nombre de descendants). Prenons l'exemple suivant:
<div style="width: 0;">
<span style="color: blue; position: relative;">Hi</span> <b>there</b>.
</div>
La propriété width
est définie sur 0 afin que la ligne entre "Hi" et "here".
Lorsque le contexte de mise en forme intégrée pour cette situation est représenté sous forme d'arborescence, il se présente comme suit:
{
"Line box": {
"Box <span>": {
"Text": "Hi"
}
},
"Line box": {
"Box <b>": {
"Text": "There"
}
},
{
"Text": "."
}
}
La liste plate se présente comme suit:
- (Line box, 2)
- (encadré <span>, 1)
- (Texte "Bonjour", 0)
- (Cadre de ligne, 3)
- (Box <b>, 1)
- (Texte "là", 0)
- (Texte ".", 0)
Cette structure de données est utilisée par de nombreux consommateurs: API d'accessibilité et API de géométrie telles que getClientRects
et contenteditable
.
Chacun a des exigences différentes.
Ces composants accèdent à la structure de données plate via un curseur pratique.
Le curseur possède des API, telles que MoveToNext
, MoveToNextLine
et CursorForChildren
.
Cette représentation du curseur est très efficace pour le contenu textuel, pour plusieurs raisons:
- L'itération dans l'ordre de recherche en profondeur est très rapide. Cette méthode est très utilisée, car elle est semblable aux mouvements du curseur. Comme il s'agit d'une liste plate, la recherche en profondeur n'augmente que le décalage du tableau, ce qui permet d'obtenir des itérations rapides et une localité de mémoire.
- Il fournit une recherche en largeur, ce qui est nécessaire, par exemple, pour peindre l'arrière-plan des lignes et des cases intégrées.
- Connaître le nombre de descendants permet de passer rapidement au frère suivant (il suffit d'incrémenter le décalage du tableau de ce nombre).
Arbres de propriétés
Le DOM est un arbre d'éléments (plus des nœuds de texte), et le CSS peut appliquer différents styles aux éléments.
Cela se manifeste de quatre manières:
- Layout (Mise en page) : entrées de l'algorithme de contrainte de mise en page.
- Paint (Peinture) : indique comment peindre et rasteriser l'élément (mais pas ses descendants).
- Visuel:effets de rastérisation/dessin appliqués au sous-arbre DOM, tels que les transformations, les filtres et le recadrage.
- Défilement:découpage et défilement des coins arrondis et alignés sur l'axe du sous-arbre contenu.
Les arborescences de propriétés sont des structures de données qui expliquent comment les effets visuels et de défilement s'appliquent aux éléments DOM. Ils permettent de répondre à des questions telles que: où se trouve un élément DOM donné par rapport à l'écran, compte tenu de sa taille et de sa position de mise en page ? Et quelle séquence d'opérations GPU devez-vous utiliser pour appliquer des effets visuels et de défilement ?
Les effets visuels et de défilement sur le Web sont très complexes dans leur ensemble. L'essentiel de la fonction des arbres de propriétés est donc de traduire cette complexité en une seule structure de données qui représente précisément leur structure et leur signification, tout en éliminant le reste de la complexité du DOM et du CSS. Cela nous permet d'implémenter des algorithmes de composition et de défilement avec beaucoup plus de confiance. En particulier :
- La géométrie et d'autres calculs potentiellement sujets à des erreurs peuvent être centralisés au même endroit.
- La complexité de la création et de la mise à jour des arborescences de propriétés est isolée dans une seule étape du pipeline de rendu.
- Il est beaucoup plus facile et rapide d'envoyer des arbres de propriétés à différents threads et processus que l'état DOM complet, ce qui permet de les utiliser pour de nombreux cas d'utilisation.
- Plus il y a de cas d'utilisation, plus nous pouvons tirer parti du cache de géométrie construit par-dessus, car ils peuvent réutiliser les caches des uns et des autres.
RenderingNG utilise des arbres d'établissements à plusieurs fins, y compris les suivantes:
- Séparation de la composition de la peinture et de la composition du thread principal.
- Déterminer une stratégie de composition / de dessin optimale.
- Mesure de la géométrie IntersectionObserver.
- Éviter le travail pour les éléments hors écran et les tuiles de texture du GPU.
- Cette action permet d'invalider les peintures et les trames de manière efficace et précise.
- Mesure des décalages de mise en page et des Largest Contentful Paint dans Core Web Vitals.
Chaque document Web comporte quatre arborescences de propriétés distinctes: transformation, clip, effet et défilement(*). L'arborescence de transformation représente les transformations CSS et le défilement. (Une transformation de défilement est représentée sous la forme d'une matrice de transformation 2D.) L'arborescence des clips représente les clips de débordement. L'arborescence des effets représente tous les autres effets visuels: opacité, filtres, masques, modes de combinaison et autres types de clips tels que le chemin de découpage. L'arborescence de défilement représente des informations sur le défilement, telles que la chaîne de défilements entre elles. Elle est nécessaire pour effectuer le défilement sur le thread du compositeur. Chaque nœud d'une arborescence de propriétés représente un défilement ou un effet visuel appliqué par un élément DOM. S'il a plusieurs effets, il peut y avoir plusieurs nœuds d'arborescence de propriétés dans chaque arborescence pour le même élément.
La topologie de chaque arbre est comme une représentation sporadique du DOM. Par exemple, s'il existe trois éléments DOM avec des extraits de dépassement de limite, il y aura trois nœuds d'arborescence de découpage, et la structure de l'arborescence d'extraits suivra la relation de bloc conteneur entre les extraits de dépassement. Il existe également des liens entre les arbres. Ces liens indiquent la hiérarchie DOM relative, et donc l'ordre d'application, des nœuds. Par exemple, si une transformation appliquée à un élément DOM se trouve sous un autre élément DOM avec un filtre, la transformation s'applique bien sûr avant le filtre.
Chaque élément DOM possède un état d'arborescence de propriétés, qui correspond à un 4-tuple (transformer, rogner, effet, faire défiler) qui indique les nœuds écrasant, transformation et effet ancêtres les plus proches qui prennent effet sur cet élément. C'est très pratique, car ces informations nous permettent de connaître exactement la liste des extraits, transformations et effets qui s'appliquent à cet élément, ainsi que leur ordre. Cela nous indique où il se trouve à l'écran et comment le dessiner.
Exemple
(source)
<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>
Pour l'exemple précédent (qui est légèrement différent de celui de l'introduction), voici les éléments clés des arborescences de propriétés générées:
Afficher des listes et des blocs de peinture
Un élément d'affichage contient des commandes de dessin de bas niveau (voir ici) qui peuvent être échantillonnées avec Skia. Les éléments d'affichage sont généralement simples, avec seulement quelques commandes de dessin, telles que le dessin d'une bordure ou d'un arrière-plan. L'itération de l'arborescence de peinture parcourt l'arborescence de mise en page et les fragments associés en suivant l'ordre de peinture CSS pour générer une liste d'éléments d'affichage.
Exemple :
<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>
Ce code HTML et CSS génère la liste d'affichage suivante, dans laquelle chaque cellule est un élément d'affichage:
Arrière-plan de la vue | #blue en arrière-plan |
#green en arrière-plan |
#green texte intégré |
---|---|---|---|
drawRect de taille 800 x 600 et de couleur blanche. |
drawRect de taille 100 x 100 à la position 0,0 et de couleur bleue. |
drawRect de taille 80x18 à la position 8,8 et de couleur verte. |
drawTextBlob à la position 8 et 8 avec le texte "Hello world". |
La liste des éléments à afficher est triée de l'arrière vers l'avant. Dans l'exemple ci-dessus, la div verte est placée avant la div bleue dans l'ordre DOM, mais l'ordre de peinture CSS exige que la div bleue à l'indice z négatif soit peinte avant (étape 3) la div verte (étape 4.1). Les éléments d'affichage correspondent approximativement aux étapes atomiques de la spécification d'ordre de peinture CSS. Un seul élément DOM peut générer plusieurs éléments d'affichage, par exemple #green a un élément d'affichage pour l'arrière-plan et un autre pour le texte intégré. Cette granularité est importante pour représenter toute la complexité de la spécification de l'ordre de peinture CSS, comme l'entrelacement créé par la marge négative:
<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>
La liste d'affichage suivante s'affiche, où chaque cellule correspond à un élément d'affichage:
Arrière-plan de la vue | #green en arrière-plan |
#gray en arrière-plan |
#green Texte intégré |
---|---|---|---|
drawRect au format 800 x 600 et en blanc. |
drawRect avec une taille 80 x 18 en position 8 et 8,et une couleur verte. |
drawRect avec une taille 35 x 20 en position 8,16 et une couleur grise. |
drawTextBlob avec la position 8,8 et le texte "Hello world". |
La liste des éléments à afficher est stockée et réutilisée par les mises à jour ultérieures. Si un objet de mise en page n'a pas changé lors de l'exploration de l'arborescence de peinture, ses éléments d'affichage sont copiés à partir de la liste précédente. Une optimisation supplémentaire repose sur une propriété de la spécification de l'ordre de peinture CSS : les contextes d'empilement peignent de manière atomique. Si aucun objet de mise en page n'a changé dans un contexte d'empilement, l'exploration de l'arborescence de peinture ignore le contexte d'empilement et copie l'ensemble de la séquence d'éléments d'affichage de la liste précédente.
L'état actuel de l'arborescence des propriétés est conservé lors de l'exploration de l'arborescence de peinture, et la liste des éléments d'affichage est regroupée en "blocs" d'éléments d'affichage qui partagent le même état de l'arborescence des propriétés. Cela est illustré dans l'exemple suivant:
<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>
La liste d'affichage suivante s'affiche, où chaque cellule correspond à un élément d'affichage:
Arrière-plan de la vue | #scroll en arrière-plan |
#scroll Texte intégré |
#orange en arrière-plan |
#orange texte intégré |
---|---|---|---|---|
drawRect de taille 800 x 600 et de couleur blanche. |
drawRect avec une taille de 100 x 100 en position 0,0 et une couleur rose. |
drawTextBlob avec la position 0,0 et le texte "Hello world". |
drawRect avec une taille 75 x 200 en position 0,0 et une couleur orange. |
drawTextBlob à la position 0,0 et le texte "I'm Falling" (Je tombe). |
L'arborescence des propriétés de transformation et les blocs de peinture seraient alors les suivants (simplifiés pour plus de concision):
La liste ordonnée des segments de peinture, qui sont des groupes d'éléments d'affichage et un état d'arborescence de propriétés, sont les entrées de l'étape de stratification du pipeline de rendu. La liste complète des segments de peinture pourrait être fusionnée dans une seule couche composite et échantillonnée ensemble, mais cela nécessiterait une échantillonnage coûteuse chaque fois que l'utilisateur ferait défiler la page. Une couche composée peut être créée pour chaque fragment de peinture et échantillonnée individuellement pour éviter toute re-échantillonnage, mais cela épuiserait rapidement la mémoire du GPU. L'étape de stratification doit faire des compromis entre la mémoire du GPU et la réduction des coûts en cas de modification. Une bonne approche générale consiste à fusionner les fragments par défaut, et non à fusionner les fragments de peinture dont les états d'arborescence de propriétés sont susceptibles de changer sur le thread du compositeur, comme le défilement du thread du compositeur ou les animations de transformation du thread du compositeur.
L'exemple précédent devrait idéalement produire deux calques composites:
- Couche composite 800x600 contenant les commandes de dessin :
drawRect
avec une taille de 800 x 600 et une couleur blanchedrawRect
de taille 100 x 100 à la position 0,0 et de couleur rose
- Calque composite 144x224 contenant les commandes de dessin :
drawTextBlob
avec la position 0,0 et le texte "Hello world"- traduire 0,18
rotateZ(25deg)
drawRect
de taille 75 x 200 à la position 0,0 et de couleur orangedrawTextBlob
avec la position 0,0 et le texte "Je tombe"
Si l'utilisateur fait défiler #scroll
, la deuxième couche composée est déplacée, mais aucune rastérisation n'est nécessaire.
Pour l'exemple, dans la section précédente sur les arbres de propriétés, il y a six blocs de peinture. Avec leurs états d'arborescence de propriétés (transformer, clip, effet, défilement), ils se présentent comme suit:
- Arrière-plan du document: défilement du document, extrait du document, racine, défilement du document.
- Coin horizontal, vertical et de défilement pour le div (trois segments de peinture distincts) : défilement du document, extrait du document, floutage
#one
, défilement du document. - Iframe
#one
: rotation#one
, extrait de défilement en cas de dépassement, floutage#one
, défilement div. - Iframe
#two
: échelle#two
, extrait de document, racine, défilement du document.
Cadres du moteur de composition: surfaces, surfaces de rendu et cartes de texture du GPU
Les processus de navigateur et de rendu gèrent la rastérisation du contenu, puis envoient des frames de composition au processus Viz pour présentation à l'écran. Les frames du compositeur représentent la façon de rassembler le contenu rasterisé et de le dessiner efficacement à l'aide du GPU.
Cartes
En théorie, un processeur de rendu ou un compositeur de processus de navigateur peut rastériser des pixels dans une seule texture de la taille complète de la vue du moteur de rendu et envoyer cette texture à Viz. Pour l'afficher, le compositeur d'affichage n'a qu'à copier les pixels de cette seule texture à la position appropriée dans le tampon de trame (par exemple, l'écran). Toutefois, si ce compositeur souhaite mettre à jour ne serait-ce qu'un seul pixel, il doit re-rasteriser l'intégralité du viewport et envoyer une nouvelle texture à Viz.
Au lieu de cela, la fenêtre d'affichage est divisée en tuiles. Une carte de texture GPU distincte est utilisée pour chaque carte avec les pixels échantillonnés pour une partie du viewport. Le moteur de rendu peut ensuite mettre à jour des cartes individuelles ou simplement modifier la position des cartes existantes à l'écran. Par exemple, lorsque vous faites défiler un site Web, la position des tuiles existantes est décalée vers le haut et une nouvelle tuile ne doit être échantillonnée que de temps en temps pour le contenu situé plus bas sur la page.
Quadrilatères et surfaces
Les tuiles de texture du GPU sont un type spécial de quad, qui n'est qu'un nom fantaisiste pour une catégorie de texture ou une autre. Un quad identifie la texture d'entrée et indique comment la transformer et lui appliquer des effets visuels. Par exemple, des tuiles de contenu classiques ont une transformation indiquant leur position x et y dans la grille de tuiles.
Ces tuiles rastérisées sont encapsulées dans un pass de rendu, qui est une liste de quads. La passe de rendu ne contient aucune information sur les pixels. À la place, elle contient des instructions sur l'emplacement et la méthode à utiliser pour dessiner chaque quad afin de produire la sortie de pixel souhaitée. Il existe un draw quad pour chaque tuile de texture GPU. Le compositeur d'affichage n'a qu'à itérer dans la liste des quads, en dessinant chacun d'eux avec les effets visuels spécifiés, pour produire la sortie de pixel souhaitée pour le pass de rendu. La composition de quads de dessin pour une passe de rendu peut être effectuée efficacement sur le GPU, car les effets visuels autorisés sont soigneusement choisis pour être ceux qui se mappent directement sur les fonctionnalités du GPU.
Il existe d'autres types de quads de dessin que les tuiles rasterisées. Par exemple, il existe des quads de dessin de couleur unie qui ne reposent pas du tout sur une texture, ou des quads de dessin de texture pour les textures qui ne sont pas des tuiles, comme une vidéo ou un canevas.
Il est également possible pour une image de compositeur d'intégrer une autre image de compositeur. Par exemple, le compositeur du navigateur produit un frame de compositeur avec l'UI du navigateur et un rectangle vide dans lequel le contenu du compositeur de rendu sera intégré. Autre exemple : les iFrames isolées par site. Cette intégration est effectuée via des surfaces.
Lorsqu'un compositeur envoie un frame de compositeur, il est accompagné d'un identifiant, appelé ID de surface, qui permet aux autres frames de compositeur de l'intégrer par référence. Le dernier frame de composition envoyé avec un ID de surface particulier est stocké par Viz. Un autre frame de composition peut ensuite s'y référer plus tard via un quadrillage de dessin de surface. Viz sait donc quoi dessiner. (Notez que les quads de dessin de surface ne contiennent que des ID de surface, et non des textures.)
Passes de rendu intermédiaires
Certains effets visuels, tels que de nombreux filtres ou modes de mélange avancés, nécessitent que deux quads ou plus soient dessinés sur une texture intermédiaire. La texture intermédiaire est ensuite dessinée dans un tampon de destination sur le GPU (ou éventuellement dans une autre texture intermédiaire), en appliquant l'effet visuel en même temps. Pour ce faire, un frame de composition contient en réalité une liste de passes de rendu. Il existe toujours une passe de rendu racine, qui est dessinée en dernier et dont la destination correspond au tampon d'images, et il peut y en avoir d'autres.
La possibilité de plusieurs passes de rendu explique le nom "pass de rendu". Chaque passe doit être exécutée de manière séquentielle sur le GPU, en plusieurs "passes", tandis qu'une seule passe peut être effectuée en un seul calcul GPU massivement parallèle.
Agrégation
Plusieurs cadres de composition sont envoyés à Viz et doivent être dessinés à l'écran ensemble. Cela est possible grâce à une phase d'agrégation qui les convertit en un seul frame de compositeur agrégé. L'agrégation remplace les quads de dessin de surface par les cadres de compositeur qu'ils spécifient. C'est également l'occasion d'optimiser les textures intermédiaires inutiles ou les contenus hors écran. Par exemple, dans de nombreux cas, le frame du compositeur pour une iframe isolée du site n'a pas besoin de sa propre texture intermédiaire et peut être dessiné directement dans le tampon d'images via des quads de dessin appropriés. La phase d'agrégation détermine ces optimisations et les applique en fonction de connaissances globales non accessibles aux compositeurs de rendu individuels.
Exemple
Voici les cadres du compositeur qui représentent l'exemple du début de cet article.
foo.com/index.html
surface: id=0- Pass de rendu 0:dessine sur la sortie.
- Passe de rendu quad: dessin avec un flou de 3 px et rognage dans la passe de rendu 0.
- Passe de rendu 1:
- Dessinez des quads pour le contenu des cartes de l'iframe
#one
, avec des positions X et Y pour chacune.
- Dessinez des quads pour le contenu des cartes de l'iframe
- Passe de rendu 1:
- Quadrilatère de dessin de surface: avec l'ID 2, dessiné avec une transformation de mise à l'échelle et de translation.
- Passe de rendu quad: dessin avec un flou de 3 px et rognage dans la passe de rendu 0.
- Pass de rendu 0:dessine sur la sortie.
- Surface de l'UI du navigateur: ID=1
- Passe de rendu 0:dessiner en sortie.
- Dessiner des quads pour l'interface utilisateur du navigateur (également en mode carte)
- Passe de rendu 0:dessiner en sortie.
bar.com/index.html
surface: ID=2- Passe de rendu 0:dessiner en sortie.
- Dessinez des quads pour le contenu de l'iframe
#two
, avec des positions x et y pour chacun.
- Dessinez des quads pour le contenu de l'iframe
- Passe de rendu 0:dessiner en sortie.
Illustrations par Una Kravets.