Strutture di dati chiave in 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

Diamo un'occhiata alle strutture principali dei dati, che sono input e output pipeline di rendering.

Queste strutture di dati sono:

  • I frame Tree sono composti da nodi locali e remoti che rappresentano la scelta documenti sono in quale processo di rendering e quale renderer Blink.
  • L'albero di frammenti immutabile rappresenta l'output (e l'input) della con un algoritmo di vincolo del layout.
  • Le alberi delle proprietà rappresentano le gerarchie di trasformazione, clip, effetto e scorrimento. di un documento web. e vengono utilizzati in tutta la pipeline.
  • Gli elenchi di visualizzazione e i blocchi di colore sono gli input per gli algoritmi di raster e di stratificazione.
  • I frame del compositore incapsulano superfici, superfici di rendering e texture GPU usati per disegnare usando la GPU.

Prima di analizzare queste strutture di dati, l'esempio seguente si basa su e quella della revisione dell'architettura. Questo nel documento viene utilizzato un esempio con dimostrazioni di come i dati strutture si applicano.

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

Alberi incorniciati

A volte Chrome potrebbe scegliere di eseguire il rendering di un frame multiorigine in un processo di rendering diverso rispetto al frame principale.

Nel codice di esempio, ci sono tre frame totali:

Un frame principale foo.com, contenente due iframe.

Con l'isolamento dei siti, Chromium utilizza due processi di rendering per visualizzare questa pagina web. Ogni processo di rendering ha la propria rappresentazione dell'albero di frame per la pagina web:

Due strutture di frame che rappresentano i due processi di rendering.

Un frame sottoposto a rendering in un processo diverso è rappresentato da un frame remoto. Un frame remoto contiene il numero minimo di informazioni necessarie per fungere da segnaposto nel rendering, come le sue dimensioni. In caso contrario, il frame remoto non contiene alcuna informazione necessaria per eseguire il rendering dei suoi contenuti effettivi.

Al contrario, un frame locale rappresenta un frame che passa attraverso lo standard pipeline di rendering. Il frame locale contiene tutte le informazioni necessarie per girare i dati per quel frame (come l'albero DOM e i dati di stile) in qualcosa che possono essere sottoposti a rendering e visualizzati.

La pipeline di rendering opera sulla granularità di un frammento di albero frame locale. Considera un esempio più complicato con foo.com come frame principale:

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

E il seguente frame secondario bar.com:

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

Anche se ci sono ancora solo due renderer, ora ci sono tre frame locali frammenti di albero, con due nel processo di rendering per foo.com e uno nel processo di rendering per bar.com:

Una rappresentazione dei due rendering e tre frammenti di albero di frame.

Per produrre un frame del compositore per la pagina web, Viz richiede contemporaneamente un frame di composizione dal frame principale di ciascuno i tre alberi di cornici locali e quindi le aggrega. Fai riferimento anche alla sezione relativa ai frame del compositore.

Il frame principale foo.com e il frame secondario foo.com/other-page fanno parte dello stesso albero di frame e vengono visualizzati nello stesso processo. Tuttavia, i due frame hanno comunque cicli di vita dei documenti poiché fanno parte di diversi frammenti di frame frame locali. Per questo motivo, non è possibile generare un frame del compositore per entrambi in un unico aggiornamento. Il processo di rendering non dispone di informazioni sufficienti per comporre il frame del compositore generato per foo.com/other-page direttamente nel frame del compositore per il frame principale foo.com. Ad esempio, il frame principale bar.com out-of-process potrebbe influire sulla visualizzazione dell'iframe foo.com/other-url, trasformando l'iframe con CSS o nascondendo parti dell'iframe ad altri elementi nel suo DOM.

Struttura a cascata dell'aggiornamento delle proprietà visive

Le proprietà grafiche, come il fattore di scala del dispositivo e le dimensioni dell'area visibile, influiscono sull'output visualizzato e devono essere sincronizzati tra i frammenti ad albero di frame locali. Alla radice di ogni frammento di albero di frame locale è associato un oggetto widget. Gli aggiornamenti delle proprietà visive vengono inviati al widget del frame principale prima della propagazione ai widget rimanenti dall'alto verso il basso.

Ad esempio, quando cambiano le dimensioni dell'area visibile:

Diagramma del processo spiegato nel testo precedente.

Questo processo non è istantaneo, in modo che anche le proprietà visive replicate includano un token di sincronizzazione. Il compositore Viz utilizza questo token di sincronizzazione per attendere tutti i frammenti ad albero di frame locali per inviare un frame del compositore con il token di sincronizzazione corrente. Questo processo evita la combinazione di frame del compositore con proprietà visive diverse.

L'albero a frammenti immutabile

L'albero di frammenti immutabile è l'output della fase di layout del rendering una pipeline o un blocco note personalizzato. Rappresenta la posizione e le dimensioni di tutti gli elementi sulla pagina (senza trasformazioni applicate).

Rappresentazione dei frammenti in ogni albero, con un frammento contrassegnato come layout necessario.

Ogni frammento rappresenta una parte di un elemento DOM. In genere è presente un solo frammento per elemento, ma ce ne possono essere di più se il testo è suddiviso in diverse pagine durante la stampa, o colonne in un contesto a più colonne.

Dopo il layout, ogni frammento diventa immutabile e non viene più modificato. È importante anche applicare alcune limitazioni aggiuntive. Cosa non facciamo:

  • Consenti qualsiasi "up" riferimenti nell'albero. (Un asset secondario non può avere un puntatore al relativo elemento principale.)
  • "bolla" i dati più in basso (un bambino legge solo le informazioni dei propri figli, non di quelli principali).

Queste restrizioni ci consentono di riutilizzare un frammento per un layout successivo. Senza queste restrizioni, spesso dovremmo rigenerare l'intero albero, il che è costoso.

La maggior parte dei layout è costituita da aggiornamenti incrementali, ad esempio un'app web che aggiorna una piccola parte dell'interfaccia utente in risposta al clic dell'utente su un elemento. Idealmente, il layout dovrebbe funzionare proporzionalmente a ciò che è stato effettivamente modificato sullo schermo. Possiamo ottenere questo risultato riutilizzando il maggior numero possibile di parti dell'albero precedente. Ciò significa (in genere) che dobbiamo solo ricostruire la colonna vertebrale dell'albero.

In futuro, questo design immutabile potrebbe permetterci di fare cose interessanti come il passaggio dell'albero a frammenti immutabile oltre i confini dei thread, se necessario (per eseguire fasi successive in un thread diverso), generare più alberi per un'animazione del layout fluida, o eseguire layout speculativi paralleli. Inoltre, ci offre il potenziale del layout multi-threading stesso.

Elementi con frammenti incorporati

I contenuti in linea (prevalenza del testo con stili applicati) utilizzano una rappresentazione leggermente diversa. Piuttosto che una struttura ad albero con caselle e puntatori, rappresentano i contenuti in linea in un elenco semplice che rappresenta l'albero. Il vantaggio principale è che una rappresentazione flat list per le linee è veloce, è utile per ispezionare o eseguire query su strutture di dati in linea, ed efficiente in termini di memoria. Questo è estremamente importante per il rendimento del rendering web, perché il rendering del testo è molto complesso, e può facilmente diventare la parte più lenta della pipeline, a meno che non sia molto ottimizzata.

L'elenco semplice viene creato contesto di formattazione incorporata nell'ordine di una ricerca depth-first del sottoalbero del layout in linea. Ogni voce dell'elenco è una tupla di (oggetto, numero di discendenti). Ad esempio, considera questo DOM:

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

La proprietà width è impostata su 0 in modo che la linea vada a capo tra "Hi" e "lì".

Quando il contesto di formattazione in linea per questa situazione è rappresentato da una struttura ad albero, avrà il seguente aspetto:

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

L'elenco semplice ha il seguente aspetto:

  • (Riquadro a linee, 2)
  • (Riquadro <span>, 1)
  • (Testo "Ciao", 0)
  • (Riquadro a linee, 3)
  • (Riquadro <b>, 1)
  • (Testo "lì", 0)
  • (Testo ".", 0)

Esistono molti consumatori di questa struttura di dati: API di accessibilità, e le API di geometria come getClientRects, e contenteditable. Ognuno ha requisiti diversi. Questi componenti accedono alla struttura dei dati piatti tramite un cursore pratico.

Il cursore include API, ad esempio MoveToNext, MoveToNextLine, CursorForChildren. Questa rappresentazione del cursore è molto efficace per i contenuti testuali per diversi motivi:

  • L'iterazione dell'ordine di ricerca depth-first è molto veloce. Viene usato molto spesso perché è simile ai movimenti del cursore. Poiché si tratta di un elenco semplice, la ricerca depth-first consiste semplicemente nell'incrementare l'offset dell'array, che fornisce iterazioni rapide e località di memoria.
  • Fornisce una ricerca wide-first, necessaria quando, ad esempio, dipingere lo sfondo di linee e riquadri in linea.
  • Conoscere il numero di discendenti consente di passare rapidamente al prossimo fratello (basta incrementare l'offset dell'array di quel numero).

Alberi della proprietà

Il DOM è una struttura di elementi (più nodi di testo) e CSS può applicare dagli stili agli elementi.

Esistono quattro modi per:

  • Layout: inserisce l'algoritmo del vincolo di layout.
  • Paint: come dipingere e rasterizzare l'elemento (ma non i relativi discendenti).
  • Immagini: effetti raster/disegno applicati al sottoalbero DOM come trasformazioni, filtri e ritaglio.
  • Scorrimento: angolo allineato all'asse e arrotondato taglio e scorrimento del sottoalbero contenuto.

Gli alberi delle proprietà sono strutture di dati che spiegano come gli effetti visivi e di scorrimento vengono applicati agli elementi DOM. Forniscono i mezzi per rispondere a domande quali: dove, rispetto allo schermo, è un determinato elemento DOM, date le dimensioni e la posizione del layout? Infine, quale sequenza di operazioni GPU dovrebbe essere utilizzata per applicare effetti visivi e di scorrimento?

Gli effetti visivi e di scorrimento sul web sono molto complicati nel loro complesso. La cosa più importante che gli alberi di proprietà fanno è tradurre questa complessità in un'unica struttura di dati che ne rappresenti con precisione la struttura e il significato, e, allo stesso tempo, rimuovere il resto della complessità di DOM e CSS. In questo modo possiamo implementare algoritmi per la composizione e lo scorrimento con maggiore sicurezza. In particolare:

  • Geometria potenzialmente soggetta a errori e altri calcoli possono essere centralizzate in un unico posto.
  • La complessità della costruzione e dell'aggiornamento di alberi di proprietà è isolato in una fase della pipeline di rendering.
  • È molto più facile e veloce inviare alberi di proprietà a thread e processi diversi rispetto allo stato DOM completo, consentendone così l'uso per molti casi d'uso.
  • Più sono i casi d'uso, maggiori sono i risultati ottenuti dalla memorizzazione nella cache della geometria basata su perché possono riutilizzare i dati .

RenderingNG utilizza gli alberi di proprietà per molti scopi, tra cui:

  • Separazione della composizione dal disegno e della composizione dal thread principale.
  • Determinare una strategia di composizione / disegno ottimale.
  • Misurazione IntersectionObserver la geometria di testo.
  • Evitando di lavorare per elementi fuori schermo e riquadri di texture GPU.
  • Annullamento di immagini e raster in modo efficiente e preciso.
  • Misurazione cambiamento del layout e Largest Contentful Paint, in Core Web Vitals.

Ogni documento web dispone di quattro strutture di proprietà separate: trasformazione, ritaglio, effetto e scorrimento.(*) L'albero della trasformazione rappresenta le trasformazioni e lo scorrimento CSS. Una trasformazione di scorrimento è rappresentata come una matrice di trasformazione 2D. La struttura ad albero rappresenta clip extra. L'albero degli effetti rappresenta tutti gli altri effetti visivi: opacità, filtri, maschere modalità di fusione e altri tipi di clip come clip-path. L'albero di scorrimento rappresenta informazioni sullo scorrimento, ad esempio la modalità di scorrimento catenano; necessario per eseguire lo scorrimento sul thread del compositore. Ogni nodo in una struttura ad albero delle proprietà rappresenta uno scorrimento o un effetto visivo applicato da un elemento DOM. Se si verificano più effetti, potrebbe esserci più di un nodo dell'albero delle proprietà in ogni albero per lo stesso elemento.

La topologia di ogni albero è come una rappresentazione sparsa del DOM. Ad esempio, se sono presenti tre elementi DOM con clip extra, ci saranno tre nodi ad albero dei clip, e la struttura dei clip ad albero la relazione del blocco contenitore tra i clip extra. Sono inoltre presenti collegamenti tra gli alberi. Questi link indicano la gerarchia DOM relativa, e quindi l'ordine di applicazione dei nodi. Ad esempio, se una trasformazione su un elemento DOM si trova al di sotto di un altro elemento DOM con un filtro, ovviamente la trasformazione viene applicata prima del filtro.

Ogni elemento DOM ha uno stato ad albero delle proprietà, che è costituita da 4 tuple (trasformazione, clip, effetto, scorrimento) che indica il clip predecessore più vicino, i nodi di trasformazione e dell'albero degli effetti che hanno effetto su quell'elemento. È una soluzione molto pratica, perché con queste informazioni sappiamo esattamente l'elenco dei clip, trasformazioni ed effetti applicabili a quell'elemento, e in quale ordine. Questo ci indica dove si trova sullo schermo e come disegnarlo.

Esempio

(fonte)

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

Nell'esempio precedente (che è leggermente diverso da quello dell'introduzione), Di seguito sono riportati gli elementi chiave degli alberi di proprietà generati:

Un esempio dei vari elementi della struttura ad albero delle proprietà.

Visualizza elenchi e blocchi di colore

Un elemento di visualizzazione contiene comandi di disegno di basso livello (vedi qui). che possono essere rasterizzati Skia. Gli elementi di visualizzazione sono in genere semplici, con pochi comandi di disegno, ad esempio tracciare un bordo o uno sfondo. Il percorso dell'albero del disegno viene ripetuto sull'albero del layout e sui frammenti associati seguendo l'ordine di pittura CSS per produrre un elenco di elementi da visualizzare.

Ad esempio:

Una casella blu con la scritta &quot;Hello World&quot; all&#39;interno di un rettangolo 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>

Questo codice HTML e CSS produrrà il seguente elenco di visualizzazione, in cui ogni cella è un elemento di visualizzazione:

Sfondo della visualizzazione #blue in background #green in background Testo in linea #green
drawRect con dimensioni 800x600 e colore bianco. drawRect con dimensioni 100 x 100 nella posizione 0,0 e colore blu. drawRect con dimensioni 80 x 18 nella posizione 8,8 e di colore verde. drawTextBlob con posizione 8,8 e testo "Hello world".

L'elenco degli elementi visualizzati viene ordinato in ordine decrescente. Nell'esempio precedente, il div verde si trova prima del div blu nell'ordine DOM, ma l'ordine di colorazione CSS richiede che l'elemento div blu negativo con z-index venga visualizzato prima (passaggio 3) del tag div verde (passaggio 4.1). Gli elementi visualizzati corrispondono approssimativamente ai passaggi atomici della specifica dell'ordine di colorazione CSS. Un singolo elemento DOM può generare diversi elementi di visualizzazione, ad esempio su come #green ha un elemento di visualizzazione per lo sfondo e un altro per il testo in linea. Questa granularità è importante per rappresentare l'intera complessità della specifica dell'ordine di colorazione CSS, come l'interfoliazione creata da un margine negativo:

Un rettangolo verde con una casella grigia parzialmente sovrapposta e la scritta &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>

Questo produce il seguente elenco di visualizzazione, in cui ogni cella è un elemento di visualizzazione:

Sfondo della visualizzazione #green in background #gray in background Testo in linea #green
drawRect con dimensioni 800x600 e colore bianco. drawRect con dimensioni 80 x 18 nella posizione 8,8 e di colore verde. drawRect con dimensioni 35 x 20 nella posizione 8 e 16 e colore grigio. drawTextBlob con posizione 8,8 e testo "Hello world".

L'elenco degli articoli visualizzati viene archiviato e riutilizzato tramite aggiornamenti successivi. Se un oggetto di layout non è cambiato durante il percorso, gli elementi visualizzati vengono copiati dall'elenco precedente. Un'ulteriore ottimizzazione si basa su una proprietà della specifica dell'ordine di colorazione CSS: i contesti di sovrapposizione vengono visualizzati a livello atomico. Se nessun oggetto di layout è stato modificato all'interno di un contesto di sovrapposizione, la camminata ad albero salta il contesto di sovrapposizione e copia l'intera sequenza di elementi di visualizzazione dall'elenco precedente.

L'attuale stato dell'albero della proprietà viene mantenuto durante la camminata e l'elenco degli elementi visualizzati è raggruppato in "blocchi" di elementi di visualizzazione che condividono lo stesso stato della struttura ad albero delle proprietà. Ciò è dimostrato nell'esempio seguente:

Un riquadro rosa con un riquadro arancione inclinato.

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

Questo produce il seguente elenco di visualizzazione, in cui ogni cella è un elemento di visualizzazione:

Sfondo della visualizzazione #scroll in background Testo in linea #scroll #orange in background Testo in linea #orange
drawRect con dimensioni 800x600 e colore bianco. drawRect con dimensioni 100 x 100 nella posizione 0,0 e di colore rosa. drawTextBlob con posizione 0,0 e il testo "Hello world". drawRect con dimensioni 75 x 200 nella posizione 0,0 e di colore arancione. drawTextBlob con posizione 0,0 e il testo "Sto scendendo".

L'albero della proprietà di trasformazione e i blocchi di colorazione sarebbero quindi (semplificati per brevità):

Un&#39;immagine della tabella precedente, le prime due celle nel blocco 1, la terza nel blocco 2, le ultime due celle nel blocco 3.

L'elenco ordinato di frammenti di vernice, ovvero gruppi di elementi di visualizzazione e uno stato della struttura ad albero delle proprietà, sono gli input per la fase di stratificazione della pipeline di rendering. L'intero elenco di blocchi di colore potrebbe essere unito in un unico strato composito e rasterizzato insieme, ma richiederebbe una costosa rasterizzazione ogni volta che l'utente scorreva la pagina. Si potrebbe creare uno strato composito per ogni porzione di vernice e rasterizzati singolarmente per evitare ogni operazione di rasterizzazione, ma ciò esaurirebbe rapidamente la memoria GPU. Il passaggio di stratificazione deve scendere a compromessi tra la memoria GPU e ridurre i costi in caso di cambiamenti. Un buon approccio generale consiste nell'unire i chunk per impostazione predefinita, e non unire blocchi di colore con stati dell'albero delle proprietà che dovrebbero cambiare nel thread del compositore, ad esempio le animazioni di trasformazione compositor-thread o compositor-thread.

L'esempio precedente dovrebbe idealmente produrre due strati compositi:

  • Un livello composito 800 x 600 contenente i comandi di disegno:
    1. drawRect con dimensioni 800 x 600 e colore bianco
    2. drawRect con dimensioni 100 x 100 nella posizione 0,0 e di colore rosa
  • Un livello composito di 144 x 224 contenente i comandi di disegno:
    1. drawTextBlob con posizione 0,0 e il testo "Hello world"
    2. traduci 0,18
    3. rotateZ(25deg)
    4. drawRect con dimensioni 75 x 200 nella posizione 0,0 e di colore arancione
    5. drawTextBlob con posizione 0,0 e il testo "Sto scendendo"

Se l'utente scorre #scroll, viene spostato il secondo strato composito, ma non è necessaria alcuna rasterizzazione.

Ad esempio, della sezione precedente sugli alberi di proprietà, ci sono sei porzioni di vernice. Insieme agli stati dell'albero delle proprietà (trasformazione, clip, effetto, scorrimento), sono:

  • Sfondo documento: scorrimento documento, clip documento, radice, scorrimento documento.
  • Angolo orizzontale, verticale e a scorrimento per div (tre blocchi di colore separati): scorrimento documento, clip documento, #one sfocatura, scorrimento documento.
  • iframe #one: rotazione di #one, clip di scorrimento extra, sfocatura #one, scorrimento div.
  • iframe #two: scala #two, clip documento, radice, scorrimento documento.

Frame del compositore: superfici, superfici di rendering e riquadri di texture GPU

Il browser e i processi di rendering gestiscono la rasterizzazione dei contenuti, quindi inviare frame del compositore al processo Viz per la presentazione sullo schermo. I frame del compositore rappresentano la modalità di unione dei contenuti rasterizzati ed efficiente utilizzando la GPU.

Riquadri

In teoria, un processo di rendering o un compositore dei processi del browser potrebbe rasterizzare i pixel in una singola texture a grandezza naturale dell'area visibile del renderer e inviare la texture a Viz. Per visualizzarlo, il compositore deve semplicemente copiare i pixel da quella singola texture nella posizione appropriata nel buffer del fotogramma (ad esempio lo schermo). Tuttavia, se il compositore volesse aggiornare anche un singolo pixel, sarebbe necessario rasterizzare l'area visibile completa e inviare una nuova texture a Viz.

L'area visibile viene invece suddivisa in riquadri. Un riquadro di texture GPU separato fa retromarcia ogni riquadro con i pixel rasterizzati per parte dell'area visibile. Il renderer può quindi aggiornare singoli riquadri o anche basta cambiare la posizione dei riquadri esistenti sullo schermo. Ad esempio, quando scorri un sito web, la posizione dei riquadri esistenti si spostava verso l'alto e solo occasionalmente un nuovo riquadro dovrà essere rasterizzato per i contenuti più in basso nella pagina.

Quattro riquadri.
Questa immagine mostra l'immagine di una giornata di sole, con quattro riquadri. Quando si scorre, inizia a visualizzare un quinto riquadro. Uno dei riquadri ha un solo colore (azzurro cielo), e c'è un video e un iframe nella parte superiore.

Quad e piattaforme

I riquadri di texture GPU sono un tipo speciale di quad, che è solo un nome fantasioso per una categoria di texture o un'altra. Un quad identifica la texture di input e indica come trasformarla e applicarvi effetti visivi. Ad esempio, i riquadri di contenuti normali presentano una trasformazione che indica la posizione x e y nella griglia dei riquadri.

Riquadri texture GPU.

Questi riquadri rasterizzati vengono avvolti in un pass di rendering, che è un elenco di quad. Il pass di rendering non contiene informazioni sui pixel; vengono fornite istruzioni su dove e come disegnare ogni quadrato per produrre l'output dei pixel desiderato. È presente un quad di disegno per ogni riquadro di texture GPU. Il compositore display deve solo ripetere l'elenco di quad, disegnando ognuna con gli effetti visivi specificati, per produrre l'output pixel desiderato per il passaggio di rendering. La composizione di quattro quad per un rendering passato può essere eseguita in modo efficiente sulla GPU, perché gli effetti visivi consentiti vengono scelti con cura in modo che corrispondano direttamente alle funzionalità GPU.

Oltre ai riquadri rasterizzati, esistono altri tipi di quadricipiti. Ad esempio, esistono quadri di disegno a colori a tinta unita non supportati da una texture. o quadri di disegno delle texture per texture non riquadri come video o canvas.

È anche possibile che un frame del compositore incorpora un altro frame del compositore. Ad esempio, il compositore del browser produce un frame del compositore con l'interfaccia utente del browser, e un rettangolo vuoto in cui incorporano i contenuti del compositore di rendering. Un altro esempio sono gli iframe isolati per i siti. L'incorporamento viene realizzato tramite le superfici.

Quando un compositore invia un frame del compositore, è accompagnato da un identificatore, chiamato surface ID, che consente ad altri frame del compositore di incorporarlo per riferimento. Il frame del compositore più recente inviato con un determinato ID superficie viene archiviato da Viz. Un altro frame del compositore può quindi farvi riferimento in un secondo momento tramite un quad surface draw quad, e quindi Viz sa cosa disegnare. Tieni presente che i quadricipiti contengono solo gli ID superficie e non le texture.

Pass di rendering intermedi

Alcuni effetti visivi, ad esempio molti filtri o modalità di fusione avanzate, richiede che due o più quadri siano disegnati su una texture intermedia. Quindi la texture intermedia viene inserita in un buffer di destinazione sulla GPU (o eventualmente in un'altra texture intermedia). applicando contemporaneamente l'effetto visivo. Per consentire ciò, un frame del compositore contiene in realtà un elenco di passaggi di rendering. C'è sempre un pass di rendering principale, che viene disegnato per ultimo e la cui destinazione corrisponde al buffer di frame, e potrebbero essercene altre.

La possibilità di avere più passaggi di rendering spiega il nome "render pass". Ogni pass deve essere eseguito in sequenza sulla GPU, in più "pass", mentre un singolo passaggio può essere completato in un singolo calcolo GPU molto parallelo.

Aggregazione

Vengono inviati a Viz più frame del compositore, e devono essere disegnati insieme sullo schermo. Ciò è possibile grazie a una fase di aggregazione che li converte in un singolo un frame compositore aggregato. L'aggregazione sostituisce i quadricipiti di superficie da parte dei frame del compositore specificati. È anche un'opportunità per eliminare texture intermedie non necessarie o contenuti fuori schermo. Ad esempio, in molti casi il frame del compositore per un iframe isolato in un sito non ha bisogno di una propria texture intermedia, e possono essere disegnate direttamente nel buffer del frame tramite quad di disegno appropriati. La fase di aggregazione determina queste ottimizzazioni e le applica sulla base di conoscenze globali non accessibili ai singoli compositori di rendering.

Esempio

Questi sono i frame del compositore che rappresentano l'esempio dall'inizio questo post.

  • Piattaforma foo.com/index.html: id=0
    • Passaggio 0 del rendering: disegna nell'output.
      • Quadratura di disegno del passaggio del rendering: disegna con una sfocatura di 3 px e posiziona il clip nel passaggio di rendering pari a 0.
        • Pass di rendering 1:
            .
          • Disegna quad per i contenuti dei riquadri dell'iframe #one, con posizioni x e y per ciascuno.
      • Quadruplo di disegno della superficie: con ID 2, disegnato con la trasformazione in scala e trasla.
  • Piattaforma UI del browser: ID=1
    • Passaggio 0 del rendering: disegna nell'output.
      • Disegna quadricipiti per l'interfaccia utente del browser (anche affiancati)
  • Piattaforma bar.com/index.html: ID=2
    • Passaggio 0 del rendering: disegna nell'output.
      • Disegna dei quad per i contenuti dell'iframe #two, specificando le posizioni x e y per ciascuno.

Illustrazioni di Una Kravets.