Principales structures de données dans 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

Examinons les principales structures de données, qui sont les entrées et les sorties des pipeline de rendu.

Ces structures de données sont:

  • Les arborescences de frames sont composées de nœuds locaux et distants qui représentent les ressources dans quel processus de rendu et quel moteur de rendu Blink.
  • L'arborescence de fragments immuables représente la sortie (et l'entrée) de la de contrainte de mise en page.
  • Les arborescences de propriétés représentent les hiérarchies des transformations, des extraits, des effets et des défilements. d'un document Web. Ceux-ci sont utilisés tout au long du pipeline.
  • Les listes d'affichage et les morceaux de peinture sont les entrées des algorithmes de trame et de superposition.
  • Les cadres compositeurs encapsulent les surfaces, les surfaces de rendu et la texture GPU des tuiles utilisées pour dessiner à l'aide du GPU.

Avant de passer en revue ces structures de données, l'exemple suivant s'appuie sur l'un dans la section Revue de l'architecture. Ce est utilisé tout au long de ce document, avec des démonstrations de la façon dont les données les structures 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>

Encadrer des arbres

Chrome peut parfois choisir d'afficher un frame multi-origine dans un processus de rendu différent de son cadre parent.

Dans l'exemple de code, il y a trois frames au total:

Un cadre parent foo.com, contenant deux iframes.

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:

Deux arborescences de cadres représentant les deux processus de rendu.

Un frame rendu dans un processus différent est représenté sous la forme d'un frame distant. Un frame distant contient les informations minimales nécessaires pour agir comme un espace réservé dans le rendu, telles que ses dimensions, par exemple. Sinon, l'image distante ne contient aucune information nécessaire à l'affichage de son contenu réel.

En revanche, une trame locale représente une trame qui passe par pipeline de rendu. Le cadre local contient toutes les informations nécessaires pour transformer les données de ce frame (comme l'arborescence DOM et les données de style) dans un élément pouvant être affichées et affichées.

Le pipeline de rendu opère sur la précision d'un fragment de l'arborescence des frames locaux. Prenons un exemple plus complexe avec foo.com comme frame principal:

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

Et le sous-cadre bar.com suivant:

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

Bien qu'il n'y ait toujours que deux moteurs de rendu, il existe maintenant trois frames locaux fragments d'arborescence, dont deux sont en cours de rendu pour foo.com et un autre pour de rendu pour bar.com:

Représentation des deux rendus et de trois fragments d&#39;arborescence de frames.

Pour produire un cadre de compositeur pour la page Web, Viz demande simultanément un frame compositeur à partir du frame racine de chacun des les trois arbres de cadre locaux, puis les regroupe. Reportez-vous également à la section Cadres compositeurs.

Le cadre principal foo.com et le sous-cadre foo.com/other-page font partie de la même arborescence de frames et sont affichés selon le même processus. Cependant, les deux frames ont toujours des images cycles de vie des documents car ils font partie de différents fragments d'arborescence de trames locales. Pour cette raison, il est impossible de générer une image de compositeur pour les deux en une seule mise à jour. Le processus d'affichage ne dispose pas de suffisamment d'informations pour combiner le frame de compositeur généré pour foo.com/other-page directement dans le cadre du compositeur pour le 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 du code CSS ou en masquant certaines parties de l'iFrame avec d'autres éléments dans son DOM.

Cascade de mise à jour des propriétés visuelles

Les propriétés visuelles telles que le facteur d'échelle de l'appareil et la taille de la fenêtre d'affichage affectent le résultat affiché. et doivent être synchronisés entre les fragments d'arborescence de trames locales. La racine de chaque fragment d'arborescence de frames locaux est associée à un objet widget. Les mises à jour des propriétés visuelles sont transmises au widget du frame principal avant d'être propagées. vers les autres widgets, de haut en bas.

Par exemple, lorsque la taille de la fenêtre d'affichage change:

Schéma du processus expliqué dans le texte précédent.

Ce processus n'est pas instantané, les propriétés visuelles répliquées incluent également un jeton de synchronisation. Le compositeur Viz utilise ce jeton de synchronisation pour attendre tous les fragments de l'arborescence des frames locaux. pour envoyer un frame compositeur avec le jeton de synchronisation actuel. Ce processus évite de mélanger des images compositeur avec différentes propriétés visuelles.

Arborescence des fragments immuables

L'arborescence de fragments immuables est la sortie de l'étape de mise en page du rendu. pipeline. Il représente la position et la taille de tous les éléments de la page (sans l'application de transformations).

Représentation des fragments dans chaque arborescence, avec un fragment marqué comme nécessitant une mise en page.

Chaque fragment représente une partie d'un élément DOM. Il n'y a généralement qu'un seul fragment par élément, mais il peut y en avoir plus s'il est réparti sur différentes pages lors de l'impression, ou colonnes dans un contexte à plusieurs colonnes.

Après la mise en page, chaque fragment devient immuable et n'est plus jamais modifié. Il est important de noter que nous appliquons également quelques restrictions supplémentaires. Ce que nous ne faisons pas:

  • Autoriser n'importe quelle limite de référence dans l'arborescence. (Un enfant ne peut pas avoir de pointeur vers son parent.)
  • "info-bulle" des données plus détaillées dans l'arborescence (un enfant lit uniquement les informations de ses enfants, et non de ses parents).

Ces restrictions nous permettent de réutiliser un fragment pour une mise en page ultérieure. Sans ces restrictions, il nous faudrait souvent régénérer l'arborescence entière, 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 qui met à jour une petite partie de l'interface utilisateur en réponse à un clic de l'utilisateur sur un élément. Idéalement, la mise en page ne devrait fonctionner que de manière proportionnelle à ce qui a réellement changé à l'écran. Pour ce faire, nous pouvons réutiliser autant de parties de l'arborescence précédente que possible. Cela signifie (généralement) que nous avons seulement besoin de reconstruire la colonne vertébrale de l'arbre.

À l'avenir, cette conception immuable pourrait nous permettre de faire des choses intéressantes comme la transmission de l'arborescence de fragments immuable aux limites des threads si nécessaire. (pour effectuer les phases suivantes sur un thread différent), générer plusieurs arbres pour obtenir 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. Plutôt qu'une structure arborescente avec des cases et des pointeurs, nous représentons le contenu intégré dans une liste plate représentant l'arborescence. Le principal avantage est qu'une représentation en liste plate pour les encarts est rapide, utiles pour inspecter ou interroger les structures de données intégrées, et économes en mémoire. C'est extrêmement important pour les performances de rendu Web, car le rendu du texte est très complexe, et peuvent facilement devenir la partie la plus lente du pipeline, à moins qu'elle ne soit hautement optimisée.

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 de (objet, nombre de descendants). Prenons l'exemple du DOM 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 passe à la ligne "Hi" (Bonjour). et « là ».

Lorsque le contexte de mise en forme intégrée dans cette situation est représenté sous forme d'arborescence, elle 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:

  • (Zone de ligne, 2)
  • (encadré <span>, 1)
  • (Texte "Bonjour", 0)
  • (Zone de ligne, 3)
  • (encadré <b>, 1)
  • (Envoie "Ici", 0)
  • (Texte ".", 0)

De nombreux utilisateurs de cette structure de données: les API d'accessibilité, et les API Geometry comme getClientRects, et contenteditable. Chacune d'elles présente des exigences différentes. Ces composants accèdent à la structure de données plate via un curseur pratique.

Le curseur comporte 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 axée sur la profondeur est très rapide. Il est utilisé très souvent parce qu'il est similaire aux mouvements du curseur de saisie. Comme il s'agit d'une liste plate, la recherche axée sur la profondeur ne fait qu'incrémenter le décalage du tableau. en fournissant des itérations rapides et une localité de mémoire.
  • Il fournit une recherche globale, ce qui est nécessaire lorsque, par exemple, en peignant l'arrière-plan des lignes et des cadres intégrés.
  • Le fait de connaître le nombre de descendants permet de passer rapidement au frère suivant (il suffit d'incrémenter le tableau de décalage de ce nombre).

Arbres immobiliers

Le DOM est une arborescence d'éléments (plus des nœuds de texte) et CSS peut appliquer diverses aux éléments.

Cela se présente de quatre façons:

  • Layout (Mise en page) : entrées de l'algorithme de contrainte de mise en page.
  • Peinture:comment peindre et matricier l'élément (mais pas ses descendants).
  • Visuel:effets de trame/de dessin appliqués à la sous-arborescence DOM comme les transformations, les filtres et le rognage.
  • Défilement:les angles sont alignés dans les axes et les angles arrondis rognage et défilement de la sous-arborescence contenue.

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 fournissent les moyens de répondre à des questions telles que: où, par rapport à l'écran, est un élément DOM donné, compte tenu de la taille et de la position de sa mise en page ? Quelle séquence d'opérations GPU devez-vous utiliser pour appliquer des effets visuels et de défilement ?

Sur le Web, les effets visuels et de défilement sont très compliqués dans toute leur splendeur. Les arbres de propriétés doivent avant tout transmettre 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 pour la composition et le défilement avec beaucoup plus de confiance. En particulier :

  • Géométries et autres calculs potentiellement sujets aux erreurs peuvent être centralisées en un seul endroit.
  • Complexité de la construction et de la mise à jour des arborescences de propriétés est isolé en une seule étape du pipeline de rendu.
  • Il est beaucoup plus facile et plus rapide d'envoyer des arborescences de propriétés à différents threads et processus qu'avec un état DOM complet. ce qui permet de les utiliser dans de nombreux cas d'utilisation.
  • Plus il y a de cas d'utilisation, plus nous obtenons de victoires grâce à la mise en cache des géométries construite sur le dessus, car ils peuvent réutiliser les uns des autres caches.

RenderNG utilise les arborescences de propriétés à de nombreuses fins, y compris les suivantes:

  • Séparation de la composition de la peinture et du fil principal.
  • Déterminer une stratégie de composition / de dessin optimale.
  • Mesure IntersectionObserver et la géométrie.
  • Éviter d'utiliser des éléments hors écran et des tuiles de texture GPU.
  • Cette action permet d'invalider les peintures et les trames de manière efficace et précise.
  • Mesure Layout Shift et Largest Contentful Paint dans les métriques Core Web Vitals.

Chaque document Web possède quatre arborescences de propriétés distinctes: transformation, extrait, effet et défilement(*). L'arborescence des transformations 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 extraits représente extraits supplémentaires. L'arborescence des effets représente tous les autres effets visuels: opacité, filtres, masques, les modes de fusion et d'autres types d'extraits, comme le chemin de découpage. L'arborescence de défilement représente des informations sur le défilement, comme la façon dont les défilements chaîne. il est nécessaire pour faire défiler le fil de discussion du compositeur. Dans une arborescence de propriétés, chaque nœud représente un défilement ou un effet visuel appliqué par un élément DOM. S'il s'avère qu'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 creuse du DOM. Par exemple, si trois éléments DOM contiennent des extraits de dépassement, trois nœuds "Clip tree" (Arborescence de clips) et la structure de l'arborescence des extraits la relation du 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 sur un élément DOM se trouve sous un autre élément DOM avec un filtre, la transformation s'applique avant le filtre.

Chaque élément DOM possède un état d'arborescence de propriétés. soit un 4-tuple (transformation, rognage, effet, défilement) qui indique le clip de l'ancêtre le plus proche, et appliquer des nœuds d'arborescence qui prennent effet à cet élément. C'est très pratique, car avec ces informations, nous connaissons exactement la liste des extraits, les transformations et les effets qui s'appliquent à cet élément, et dans quel 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 diffère légèrement de celui de l'introduction), Voici les principaux éléments des arborescences de propriétés générées:

Exemple des différents éléments de l&#39;arborescence de propriétés.

Afficher des listes et des blocs de peinture

Un élément d'affichage contient des commandes de dessin de niveau inférieur (voir cliquez ici). qui peuvent être rastérisées avec Skia. Les éléments d'affichage sont généralement simples, avec seulement quelques commandes de dessin, comme dessiner une bordure ou un arrière-plan. L'arborescence de mise en page parcourt l'arborescence de mise en page et les fragments associés en fonction de l'ordre de peinture CSS. pour générer une liste d'éléments display.

Exemple :

Cadre bleu avec les mots &quot;Hello world&quot; à l&#39;intérieur d&#39;un rectangle vert.

<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 produit la liste d'affichage suivante : où 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 au format 800 x 600 et en blanc. drawRect avec une taille de 100 x 100 en position 0,0 et une couleur bleue. drawRect avec une taille 80 x 18 en position 8 et 8,et une couleur verte. drawTextBlob à la position 8 et 8 avec le texte "Hello world".

La liste des éléments à afficher est triée dans l'ordre chronologique. Dans l'exemple ci-dessus, le div vert est placé avant le div bleu, dans l'ordre DOM. mais l'ordre de peinture CSS exige que le z-index négatif div peint avant (étape 3) le tag div vert. (é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 display, Par exemple, #green a un élément display pour l'arrière-plan et un autre élément display pour le texte intégré. Cette précision est importante pour représenter toute la complexité de la spécification des ordres de peinture CSS, comme l'entrelacement créé par une marge négative:

Rectangle vert avec une zone grise en partie superposée et le texte &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>

Vous obtenez la liste d'affichage suivante, dans laquelle chaque cellule est 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 à la position 8 et 8 avec le texte "Hello world".

Cette liste est stockée et réutilisée par les mises à jour ultérieures. Si un objet de mise en page n'a pas changé pendant le parcours ses éléments à afficher 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 empilés sont atomiques. Si aucun objet de mise en page n'a changé dans un contexte d'empilement, la promenade en arbre de peinture ignore le contexte d'empilement et copie la séquence complète d'éléments d'affichage de la liste précédente.

L'état actuel de l'arborescence de propriété est maintenu pendant le parcours de l'arbre de la propriété. et la liste des éléments display est regroupée par fragments d'éléments display partageant le même état d'arborescence de propriétés. Ce processus est illustré dans l'exemple suivant:

Cadre rose avec un cadre orange incliné.

<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>

Vous obtenez la liste d'affichage suivante, dans laquelle chaque cellule est 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 au format 800 x 600 et en blanc. 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 morceaux de peinture seraient alors (simplifiés pour des raisons de concision):

Une image du tableau précédent, les deux premières cellules du bloc 1, la troisième du bloc 2, les deux dernières cellules du bloc 3.

La liste ordonnée des morceaux de peinture, qui sont des groupes d'éléments display et un état d'arborescence de propriétés, sont les entrées de l'étape de couche du pipeline de rendu. La liste complète des morceaux de peinture peut être fusionnée en une seule couche composite et rastérisée, mais cela nécessiterait une rastérisation coûteuse à chaque fois que l’utilisateur fait défiler la page. Une couche composite peut être créée pour chaque bloc de peinture. et rastérisées individuellement pour éviter toute nouvelle rastérisation, mais cela épuiserait rapidement la mémoire GPU. L'étape de couche doit faire des compromis entre la mémoire GPU et réduire les coûts en cas de changement. Une bonne approche générale consiste à fusionner les fragments par défaut, et ne pas fusionner les morceaux de peinture dont les états d'arborescence de propriétés sont susceptibles de changer sur le thread du compositeur, comme le défilement ou les animations de transformation du fil de discussion du compositeur.

L'exemple précédent devrait idéalement produire deux couches composites:

  • Calque composé de 800 x 600 contenant les commandes de dessin: <ph type="x-smartling-placeholder">
      </ph>
    1. drawRect au format 800 x 600 et en blanc
    2. drawRect avec une taille de 100 x 100 en position 0,0 et une couleur rose
  • Calque composé de 144 x 224 contenant les commandes de dessin: <ph type="x-smartling-placeholder">
      </ph>
    1. drawTextBlob avec la position 0,0 et le texte "Hello world"
    2. traduire 0,18
    3. rotateZ(25deg)
    4. drawRect avec une taille 75 x 200 en position 0,0 et une couleur orange
    5. drawTextBlob avec la position 0,0 et le texte "I'm Falling"

Si l'utilisateur fait défiler #scroll, la deuxième couche composite est déplacée, mais aucune rastérisation n'est nécessaire.

Pour cet exemple : de la section précédente sur les arborescences de propriétés, il y a six morceaux de peinture. Avec leurs états d'arborescence de propriétés (transformer, clip, effet, défilement), voici ce que vous pouvez faire:

  • Arrière-plan du document: défilement du document, clip, racine, défilement du document
  • Angles horizontaux, verticaux et de défilement pour l'élément div (trois morceaux de peinture distincts): défilement du document, clip de document, flou #one, défilement du document
  • iFrame #one: rotation #one, défilement de l'extrait dépassé, flou #one, défilement div.
  • Iframe #two: échelle #two, clip de document, racine, défilement du document.

Cadres compositeurs: surfaces, surfaces de rendu et tuiles de texture GPU

Le navigateur et les processus de rendu gèrent la rastérisation du contenu, puis soumettre des images de compositeur au processus de visualisation pour les présenter à l'écran. Les images compositeur montrent comment assembler le contenu rastérisé et la dessiner efficacement à l'aide du GPU.

Cartes

En théorie, un processus de rendu ou un compositeur de processus de navigateur pourrait rastériser des pixels en une seule texture de la taille réelle de la fenêtre d'affichage du moteur de rendu et envoyez cette texture à la visualisation. Pour l'afficher, le compositeur doit simplement copier les pixels depuis cette texture jusqu'à la position appropriée dans le tampon du frame (par exemple, l'écran). Cependant, si ce compositeur souhaite mettre à jour un seul pixel, il doit rerastériser toute la fenêtre d'affichage et envoyer une nouvelle texture à la visualisation.

Au lieu de cela, la fenêtre d'affichage est divisée en tuiles. Une tuile de texture GPU distincte sauvegarde chaque tuile avec les pixels rastérisés pour une partie de la fenêtre d'affichage. Le moteur de rendu peut ensuite mettre à jour des tuiles individuelles il suffit de modifier la position à l'écran des tuiles existantes. Par exemple, lorsque vous faites défiler un site web, la position des vignettes existantes est décalée vers le haut et une nouvelle vignette doit être rastérisée pour le contenu situé plus bas sur la page.

<ph type="x-smartling-placeholder">
</ph> Quatre vignettes.
Cette image représente une journée ensoleillée avec quatre tuiles. Lorsqu'un défilement se produit, une cinquième vignette commence à apparaître. L'une des tuiles n'a qu'une seule couleur (bleu ciel), avec une vidéo et un iFrame en haut.

Quads et surfaces

Les tuiles de texture GPU sont un type spécial de quad, qui est juste un nom fantaisie 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 normales ont une transformation indiquant leur position x et y dans la grille de tuiles.

Tuiles de texture GPU.

Ces tuiles rastérisées sont encapsulées dans une passe de rendu, qui est une liste de quads. La passe de rendu ne contient aucune information sur les pixels. Au lieu de cela, il contient des instructions indiquant où et comment dessiner chaque quad pour produire la sortie de pixels souhaitée. Il existe un draw quad pour chaque tuile de texture GPU. Le compositeur d'affichage a juste à itérer la liste des quads, en dessinant chacun avec les effets visuels spécifiés, afin de produire la sortie de pixels souhaitée pour la passe de rendu. La composition des quads pour une passe de rendu peut être effectuée efficacement sur le GPU. car les effets visuels autorisés ont été soigneusement sélectionnés pour être directement mappés aux caractéristiques du GPU.

Il existe d'autres types de quads en plus des tuiles rastérisées. Par exemple, il existe des quads de dessin avec couleur unie qui ne reposent pas du tout sur une texture. ou quads de dessin 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 de navigateur produit un frame compositeur avec l'interface utilisateur du navigateur, et un rectangle vide dans lequel le contenu du compositeur de rendu sera intégré. Autre exemple : les iFrames isolés au niveau du site. Cette représentation vectorielle continue s'effectue via des surfaces.

Lorsqu'un compositeur envoie un frame compositeur, celui-ci est accompagné d'un identifiant, appelé ID de surface, ce qui permet à d'autres cadres compositeurs de l'intégrer à l'aide d'une référence. La trame de compositeur la plus récente envoyée avec un ID de surface spécifique est stockée par Viz. Un autre cadre compositeur peut s'y référer plus tard via un quad de dessin de surface, et donc que la visualisation sait 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 fusion avancés, nécessitent que deux quadruples ou plus soient dessinés vers une texture intermédiaire. La texture intermédiaire est ensuite dessinée dans un tampon de destination sur le GPU (ou éventuellement une autre texture intermédiaire). en appliquant l'effet visuel en même temps. Pour ce faire, un cadre compositeur contient en fait une liste de passes de rendu. Il y a toujours une passe de rendu racine, qui est dessiné en dernier et dont la destination correspond au tampon du frame, et peut-être plus.

La possibilité de plusieurs passes de rendu explique le nom "rendu la carte". 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 réalisée en un seul calcul GPU massivement parallèle.

Agrégation

Plusieurs images compositeur sont envoyées à Viz, et ils doivent être dessinés ensemble sur l'écran. Cela s'effectue grâce à une phase d'agrégation qui les convertit en une trame de compositeur agrégée. L'agrégation remplace les quads de surface de dessin par les frames du compositeur qu'ils spécifient. C'est également l'occasion d'optimiser les textures intermédiaires inutiles ou le contenu hors écran. Par exemple, dans de nombreux cas, le cadre du compositeur d'un iFrame isolé du site n'a pas besoin de sa propre texture intermédiaire, et peut être dessiné directement dans le tampon du frame via des quads de dessin appropriés. La phase d'agrégation permet de déterminer les optimisations et les applique grâce à une connaissance globale qui n'est pas accessible aux compositeurs de rendu individuels.

Exemple

Voici les cadres compositeurs qui représentent l'exemple du début de ce post.

  • Surface foo.com/index.html: id=0 <ph type="x-smartling-placeholder">
      </ph>
    • 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: <ph type="x-smartling-placeholder">
            </ph>
          • Dessinez des quads pour le contenu des tuiles de l'iFrame #one, avec les positions x et y pour chacun.
      • Quadrillage du dessin de surface: ID 2, dessiné avec une mise à l'échelle et une transformation de translation.
  • Surface de l'UI du navigateur: ID=1 <ph type="x-smartling-placeholder">
      </ph>
    • Pass de rendu 0:dessine sur la sortie.
      • Dessiner quadrillage pour l'interface utilisateur du navigateur (en mosaïque également)
  • Surface bar.com/index.html: ID=2 <ph type="x-smartling-placeholder">
      </ph>
    • Pass de rendu 0:dessine sur la sortie.
      • Dessinez des quads pour le contenu de l'iFrame #two, avec les positions x et y pour chacun.

Illustrations d'Una Kravets.