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

次に、レンダリング パイプラインへの入力と出力である主なデータ構造を見てみましょう。

データ構造は次のとおりです。

  • フレームツリーは、ローカルノードとリモートノードで構成されます。これらのノードは、どのウェブ ドキュメントがどのレンダリング プロセスにあるか、どのウェブ ドキュメントがどの Blink レンダラであるかを表します。
  • 不変のフラグメント ツリーは、レイアウト制約アルゴリズムの出力(および入力)を表します。
  • プロパティ ツリーは、ウェブ ドキュメントの変換、クリップ、効果、スクロールの階層を表します。これらはパイプライン全体で使用されます。
  • ディスプレイ リストとペイント チャンクは、ラスターおよびレイヤ化アルゴリズムへの入力です。
  • コンポジタ フレームは、GPU による描画に使用されるサーフェス、レンダリング サーフェス、GPU テクスチャ タイルをカプセル化します。

これらのデータ構造について説明する前に、次の例はアーキテクチャ レビューに基づいています。この例は、このドキュメント全体で使用され、データ構造がどのように適用されるかを示します。

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

フレームツリー

Chrome は、親フレームとは異なるレンダリング プロセスでクロスオリジン フレームのレンダリングを選択することがあります。

このサンプルコードには、合計 3 つのフレームがあります。

2 つの iframe を含む親フレーム foo.com。

サイト分離により、Chromium は 2 つのレンダリング プロセスを使用してこのウェブページをレンダリングします。 各レンダリング プロセスには、そのウェブページのフレームツリーが独自に表現されています。

2 つのレンダリング プロセスを表す 2 つのフレームツリー。

別のプロセスでレンダリングされたフレームはリモート フレームとして表されます。リモート フレームは、サイズなど、レンダリングでプレースホルダとして機能するために必要な最小限の情報を保持します。それ以外の場合、リモート フレームには実際のコンテンツをレンダリングするために必要な情報が含まれません。

一方、ローカル フレームは、標準レンダリング パイプラインを通過するフレームを表します。ローカル フレームには、そのフレームのデータ(DOM ツリーやスタイルデータなど)をレンダリングおよび表示可能なものにするために必要なすべての情報が含まれています。

レンダリング パイプラインは、ローカル フレームツリー フラグメントの粒度で動作します。foo.com をメインフレームとする複雑な例を考えてみましょう。

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

次の bar.com サブフレームがあるとします。

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

レンダラは 2 つしかありませんが、ローカル フレームツリー フラグメントは 3 つになります。foo.com のレンダリング プロセスに 2 つ、bar.com のレンダリング プロセスに 1 つです。

2 つのレンダリングと 3 つのフレームツリー フラグメントの表現。

ウェブページに対して 1 つのコンポジタ フレームを生成するために、Viz は 3 つのローカル フレームツリーそれぞれのルートフレームからコンポジタ フレームを同時にリクエストし、それらを集約します。コンポジタ フレームのセクションもご覧ください。

foo.com メインフレームと foo.com/other-page サブフレームは同じフレームツリーの一部であり、同じプロセスでレンダリングされます。ただし、2 つのフレームは異なるローカル フレームツリー フラグメントの一部であるため、引き続き独立したドキュメント ライフサイクルがあります。このため、1 回の更新で両方に対して 1 つのコンポジター フレームを生成することはできません。レンダリング プロセスに十分な情報がないため、foo.com/other-page 用に生成されたコンポジタ フレームを foo.com メインフレームのコンポジタ フレームに直接合成できません。たとえば、プロセス外の bar.com 親フレームは、CSS で iframe を変換したり、DOM 内の他の要素で iframe の一部を隠したりすることで、foo.com/other-url iframe の表示に影響する可能性があります。

ビジュアル プロパティ更新ウォーターフォール

デバイスのスケール ファクタやビューポート サイズなどの視覚的プロパティは、レンダリングされた出力に影響するため、ローカルのフレームツリー フラグメント間で同期する必要があります。各ローカル フレームツリー フラグメントのルートには、ウィジェット オブジェクトが関連付けられています。ビジュアル プロパティの更新は、メインフレームのウィジェットに送信されてから、残りのウィジェットに上から下に伝播されます。

たとえば、ビューポートのサイズが変更された場合は次のようになります。

前述のテキストで説明したプロセスの図。

このプロセスは即時に行われるため、複製されたビジュアル プロパティにも同期トークンが含まれます。Viz コンポジタはこの同期トークンを使用して、すべてのローカル フレームツリー フラグメントが現在の同期トークンを含むコンポジタ フレームを送信するのを待ちます。このプロセスにより、異なる視覚的プロパティを持つコンポジタ フレームが混在するのを回避できます。

イミュータブル フラグメント ツリー

不変のフラグメント ツリーは、レンダリング パイプラインのレイアウト ステージの出力です。これは、ページ上のすべての要素の位置とサイズを表します(変換が適用されていない場合)。

各ツリー内のフラグメントを表し、1 つのフラグメントがレイアウトが必要としてマークされています。

各フラグメントは DOM 要素の一部を表します。通常、要素ごとにフラグメントは 1 つだけですが、印刷時に複数のページに分割したり、複数列のコンテキストで列を分割したりすると、フラグメントの数が増えることがあります。

レイアウト後、各フラグメントは不変になり、再度変更されることはありません。重要な点として、追加の制限もいくつか適用されます。Google がしないこと:

  • ツリー内の「上」参照をすべて許可します。(子には親へのポインタを設定できません)。
  • データを「バブル」で表示します(子は親の情報ではなく、子の情報のみを読み取ります)。

こうした制限により、フラグメントを後続レイアウトで再利用できるようになります。こうした制限がなければ、ツリー全体を再生成することが多くなり、コストがかかります。

ほとんどのレイアウトは通常、増分アップデートです。たとえば、ユーザーが要素をクリックしたときに UI のごく一部を更新するウェブアプリなどがこれに該当します。レイアウトは、画面上で実際に変更された内容に比例して動作するのが理想的です。 これは、前のツリーをできるだけ多く再利用することで実現できます。つまり、(通常は)木の背骨を再構築するだけで済みます。

将来的には、この不変の設計により、必要に応じてスレッド境界を越えて不変のフラグメント ツリーを渡す(別のスレッドで後続のフェーズを実行するため)、滑らかなレイアウト アニメーションのために複数のツリーを生成したり、並列投機的レイアウトを実行したりといった興味深い処理が可能になります。また、レイアウト自体にもマルチスレッド処理の可能性がもたらされます。

インライン フラグメント アイテム

インライン コンテンツ(主にスタイル設定されたテキスト)では、表現が若干異なります。ボックスとポインタで構成されたツリー構造ではなく、ツリーを表すフラットリストでインライン コンテンツを表現します。主なメリットは、インラインのフラットリスト表現が高速で、インライン データ構造の検査やクエリに便利であり、メモリ効率が高いことです。テキストのレンダリングは非常に複雑であり、高度に最適化しないとパイプラインの最も遅い部分になりやすいため、これはウェブ レンダリングのパフォーマンスにとって非常に重要です。

フラットリストは、インライン レイアウト サブツリーの深さ優先検索の順序で、インライン フォーマット コンテキストごとに作成されます。リスト内の各エントリは、(オブジェクト、子孫の数)のタプルです。たとえば、次の DOM について考えてみましょう。

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

width プロパティが 0 に設定されているため、行は「Hi」と「there」の間で折り返します。

この状況のインライン書式設定コンテキストをツリーとして表すと、次のようになります。

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

フラットリストは次のようになります。

  • (折れ線ボックス、2)
  • (ボックス <span>、1)
  • (テキスト「こんにちは」、0)
  • (ラインボックス、3)
  • (ボックス <b>、1)
  • (テキスト「そこ」、0)
  • (テキスト「.」, 0)

このデータ構造には、ユーザー補助 API のほか、getClientRectscontenteditable などのジオメトリ API など、さまざまな用途があります。それぞれに異なる要件があります。 これらのコンポーネントは、コンビニエンス カーソルを使用してフラットなデータ構造にアクセスします。

カーソルには、MoveToNextMoveToNextLineCursorForChildren などの API があります。このカーソル表現は、テキスト コンテンツにおいて非常に効果的です。これには次のような理由があります。

  • 深度優先検索の反復処理は非常に高速です。キャレットの動きに似ているため、よく使用されます。フラットリストであるため、深さ優先探索は配列オフセットを増分するだけであり、高速なイテレーションとメモリ局所性を実現します。
  • これは幅優先検索を提供します。これは、行ボックスやインライン ボックスの背景を描画する場合などに必要です。
  • 子孫の数がわかると、次の兄弟要素への移動が速くなります(配列のオフセットをその数だけ増やすだけです)。

プロパティ ツリー

DOM は要素(とテキストノード)のツリーであり、CSS では要素にさまざまなスタイルを適用できます。

これは次の 4 つの方法で表示されます。

  • レイアウト: レイアウト制約アルゴリズムへの入力。
  • ペイント: 要素をペイントしてラスターする方法(子孫は除く)。
  • 視覚的: 変換、フィルタ、クリッピングなど、DOM サブツリーに適用されるラスター効果や描画効果。
  • スクロール: 含まれるサブツリーを軸に揃えて角丸でクリップし、スクロールします。

プロパティ ツリーは、視覚的効果とスクロール効果が DOM 要素にどのように適用されるかを説明するデータ構造です。たとえば、特定の DOM 要素が、そのレイアウトのサイズと位置に応じて、画面に対するどこにあるか、といった疑問に答える手段となります。視覚効果やスクロール効果を適用するには、どのような GPU 操作を使用する必要がありますか?

ウェブでの視覚効果やスクロール効果は非常に複雑で、その魅力は絶大です。プロパティ ツリーが最も重要なのは、こうした複雑さを、構造と意味を正確に表す単一のデータ構造に変換し、同時に DOM と CSS のその他の複雑さを解消することです。これにより、非常に高い信頼度で合成とスクロールを行うアルゴリズムを実装できます。具体的には、次のとおりです。

  • エラーが発生しやすいジオメトリなどの計算を 1 か所に集約できます。
  • プロパティ ツリーの構築と更新の複雑さは、1 つのレンダリング パイプライン ステージに分離されます。
  • プロパティ ツリーをさまざまなスレッドやプロセスに送信する方が、完全な DOM 状態よりもはるかに簡単で高速であるため、多くのユースケースで使用できます。
  • ユースケースが増えるほど、上位に構築されたジオメトリのキャッシュから互いのキャッシュを再利用できるため、より多くのメリットが得られます。

プロパティ ツリーは、RenderingNG で次のようなさまざまな目的で使用されます。

  • ペイントからの合成とメインスレッドからの合成の分離。
  • 最適な合成 / 描画戦略の決定。
  • IntersectionObserver ジオメトリを測定する方法。
  • 画面外要素と GPU テクスチャ タイルの処理を回避。
  • ペイントとラスターを効率的かつ正確に無効化。
  • Core Web Vitals のレイアウト シフトLargest Contentful Paint の測定。

すべてのウェブ ドキュメントには、transform、clip、effect、scroll という 4 つのプロパティ ツリーがあります(*)。変換ツリーは、CSS の変換とスクロールを表します。(スクロール変換は 2D 変換行列として表されます)。クリップツリーは、オーバーフロー クリップを表します。エフェクト ツリーは、その他のすべての視覚効果(不透明度、フィルタ、マスク、ブレンドモード、その他の種類のクリップ(クリップパスなど))を表します。スクロール ツリーは、スクロールが連鎖する方法など、スクロールに関する情報を表します。コンポジタ スレッドでスクロールを行うために必要です。プロパティ ツリーの各ノードは、DOM 要素によって適用されるスクロールまたは視覚効果を表します。複数の効果がある場合は、同じ要素の各ツリーに複数のプロパティ ツリーノードが存在することがあります。

各ツリーのトポロジは、DOM のスパース表現のようなものです。たとえば、オーバーフロー クリップを含む DOM 要素が 3 つある場合は、クリップツリー ノードが 3 つになり、クリップツリーの構造はオーバーフロー クリップ間の包含ブロック関係に従います。ツリーの間にもつながりがあります。これらのリンクは、ノードの相対的な DOM 階層、つまり適用の順序を示します。たとえば、ある DOM 要素の変換が、フィルタが設定された別の DOM 要素の下にある場合、その変換は当然フィルタの前に適用されます。

各 DOM 要素にはプロパティ ツリー状態があります。これは 4 タプル(変換、クリップ、効果、スクロール)で、その要素に適用される最も近い祖先クリップ、変換、効果ツリーノードを示します。この情報によって、その要素に適用されるクリップ、変換、効果のリストとその順番が正確に把握できるため、これは非常に便利です。 これにより、画面上の位置と描画方法がわかります。

出典

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

前の例(最初に紹介した例とは若干異なります)の場合、生成されるプロパティ ツリーの主な要素は次のとおりです。

プロパティ ツリーのさまざまな要素の例。

リストを表示してチャンクをペイントする

表示オプションには、Skia でラスタライズできる低レベルの描画コマンド(こちらを参照)が含まれています。表示アイテムは通常、枠線や背景の描画など、いくつかの描画コマンドのみを使用するシンプルなものです。ペイント ツリー ウォークは、CSS のペイント順序に従ってレイアウト ツリーと関連フラグメントを反復処理して、ディスプレイ アイテム リストを生成します。

次に例を示します。

青いボックス。緑色の長方形の内側に「Hello world」というテキストが表示されている。

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

この HTML と CSS を使用すると、次のようなディスプレイ リストが生成されます。各セルは表示アイテムです。

ビューの背景 #blueのバックグラウンド #greenのバックグラウンド #green インライン テキスト
drawRect(サイズ 800x600、色: White) 位置 0,0、サイズ 100x100、色: blue の drawRect drawRect(位置 8.8、サイズ 80x18、色: 緑色) 位置 8、8、テキスト「Hello world」の drawTextBlob

アイテム リストは逆から上に並べられます。 上記の例では、DOM 順では緑の div は青の div より前に配置されますが、CSS の描画順序では、負の Z-Index の青い div が緑の div(ステップ 4.1)より前にペイントされる必要があります(ステップ 3)。表示するアイテムは、CSS のペイント順序仕様のアトミックなステップにほぼ対応します。 1 つの DOM 要素から複数の表示アイテムが作成されることがあります。たとえば、#green にインライン テキスト用のアイテムと、背景用のアイテムがあります。この粒度は、負のマージンによって作成されたインターリーブなど、CSS のペイント順序仕様の完全な複雑さを表すために重要です。

グレーのボックスが部分的に重なっている緑色の長方形と「Hello world」というテキスト。

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

これにより、次のディスプレイ リストが生成されます。各セルは 1 つのアイテムです。

ビューの背景 #greenのバックグラウンド #grayのバックグラウンド #green インライン テキスト
drawRect(サイズ 800x600、色: White) drawRect(位置 8.8、サイズ 80x18、色: 緑色) サイズ 35x20、位置 8、16、色: drawRect 位置 8、8、テキスト「Hello world」の drawTextBlob

ディスプレイ アイテム リストが保存され、後の更新で再利用されます。ペイントツリー ウォーク中にレイアウト オブジェクトが変更されていない場合、そのディスプレイ アイテムは前のリストからコピーされます。さらに、CSS のペイント順序仕様のプロパティ(スタック コンテキストのアトミック ペイント)を利用する最適化もあります。スタッキング コンテキスト内でレイアウト オブジェクトが変更されていない場合、ペイント ツリー ウォークはスタッキング コンテキストをスキップし、前のリストから表示アイテムのシーケンス全体をコピーします。

ペイントツリー ウォーク中は現在のプロパティ ツリーの状態が維持され、ディスプレイ アイテム リストは、同じプロパティ ツリー状態を共有するディスプレイ アイテムの「チャンク」にグループ化されます。これを次の例に示します。

ピンクのボックスとオレンジ色のボックスが傾いている。

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

これにより、次のディスプレイ リストが生成されます。各セルは 1 つのアイテムです。

ビューの背景 #scrollのバックグラウンド #scroll インライン テキスト #orangeのバックグラウンド #orange インライン テキスト
drawRect(サイズ 800x600、色: White) drawRect(位置 0、0、サイズ 100x100、色: ピンク) 位置が 0、0、テキストが「Hello World」の drawTextBlob drawRect(位置 0,0、サイズ 75×200、色: オレンジ色) 位置 0,0 とテキスト「I'mfalling」のdrawTextBlob

この場合、変換プロパティ ツリーとペイント チャンクは次のようになります(簡略化のために簡略化しています)。

前の表の画像。チャンク 1 の最初の 2 つのセル、チャンク 2 の最初の 2 つのセル、チャンク 3 の最後の 2 つのセル。

ペイント チャンクの順序付きリスト(表示オプションとプロパティ ツリー状態のグループ)が、レンダリング パイプラインの階層化ステップへの入力です。ペイント チャンクのリスト全体を 1 つの合成レイヤにマージしてまとめてラスタライズすることもできますが、ユーザーがスクロールするたびに高コストのラスタライズが必要になります。合成レイヤをペイント チャンクごとに作成し、個別にラスタライズすることで、すべての再ラスタライズを回避できますが、GPU メモリがすぐに枯渇します。階層化のステップでは、GPU メモリと、状況が変化した場合のコスト削減との間でトレードオフを行う必要があります。一般的なアプローチとしては、デフォルトでチャンクをマージし、コンポジタ スレッドのスクロールやコンポジタ スレッドの変換アニメーションなど、コンポジタ スレッドで変化することが予想されるプロパティ ツリー状態を持つペイント チャンクをマージしないことをおすすめします。

上記の例では、理想的には、次の 2 つの合成レイヤを生成する必要があります。

  • 描画コマンドを含む 800x600 の合成レイヤ:
    1. drawRect(サイズ 800x600、色: White)
    2. drawRect(位置 0、0、サイズ 100×100、色: ピンク)
  • 描画コマンドを含む 144x224 の合成レイヤ:
    1. 位置が 0、0、テキストが「Hello World」の drawTextBlob
    2. 0,18 相当を翻訳
    3. rotateZ(25deg)
    4. drawRect(位置 0,0、サイズ 75×200、色: オレンジ色)
    5. 位置 0,0 とテキスト「I'mfalling」のdrawTextBlob

ユーザーが #scroll をスクロールすると、2 番目の合成レイヤが移動されますが、ラスタライズは必要ありません。

では、プロパティ ツリーに関する前のセクションで説明した 6 つのペイント チャンクがあります。プロパティ ツリーの状態(変換、クリップ、効果、スクロール)と合わせて、以下のようになります。

  • ドキュメントの背景: ドキュメントのスクロール、ドキュメント クリップ、ルート、ドキュメントのスクロール。
  • div の水平方向、垂直方向、スクロール コーナー(3 つの個別のペイント チャンク): ドキュメントのスクロール、ドキュメント クリップ、#one ぼかし、ドキュメントのスクロール。
  • iframe #one: #one 回転、オーバーフロー スクロール クリップ、#one ぼかし、div スクロール。
  • iframe #two: #two 縮尺、ドキュメント クリップ、ルート、ドキュメントのスクロール。

コンポジタ フレーム: サーフェス、レンダリング サーフェス、GPU テクスチャ タイル

ブラウザとレンダリング プロセスは、コンテンツのラスタライズを管理し、画面に表示するためにコンポジタ フレームを Viz プロセスに送信します。コンポジタ フレームは、ラスター化されたコンテンツを合成し、GPU を使用して効率的に描画する方法を表します。

タイル

理論上は、レンダリング プロセスまたはブラウザ プロセス コンポジタは、レンダラ ビューポートのフルサイズのピクセルを単一のテクスチャにラスタライズし、そのテクスチャを Viz に送信できます。ディスプレイ コンポジタは、その単一のテクスチャからフレーム バッファの適切な位置(画面など)にピクセルをコピーするだけで済みます。ただし、コンポジタが 1 ピクセルでも更新したい場合は、ビューポート全体の再ラスタライズを行い、新しいテクスチャを Viz に送信する必要があります。

代わりに、ビューポートはタイルに分割されます。 個別の GPU テクスチャ タイルが、ビューポートの一部について、ラスタライズされたピクセルを使用して各タイルをバックアップします。レンダラは個々のタイルを更新することも、既存のタイルの画面上の位置を変更することもできます。たとえば、ウェブサイトをスクロールすると、既存のタイルの位置が上がるため、ページのより下にあるコンテンツ用に新しいタイルをラスタライズする必要があるのはまれです。

4 枚のタイル。
この画像は、晴れた日の 4 つのタイルを表しています。 スクロールが発生すると、5 番目のタイルの表示が開始されます。タイルの 1 つはたまたま 1 つの色(スカイブルー)のみで、その上に動画と iframe があります。

クアッドとサーフェス

GPU テクスチャ タイルは特別な種類のクワッドで、テクスチャの特定のカテゴリを表す単なる単なる名です。クワッドは入力テクスチャを識別し、そのテクスチャを変換して視覚効果を適用する方法を示します。たとえば、通常のコンテンツ タイルには、タイルグリッド内の x、y 位置を示す変換があります。

GPU テクスチャ タイル。

これらのラスタライズされたタイルは、クワッドのリストであるレンダリング パスにラップされます。レンダリング パスにはピクセル情報は含まれません。代わりに、目的のピクセル出力を生成するために、各クワッドをどこで、どのように描画するかが指示されます。GPU テクスチャ タイルごとに描画クワッドがあります。ディスプレイ コンポジタは、クワッドのリストを反復処理し、指定された視覚効果で各クワッドを描画して、レンダリング パスに必要なピクセル出力を生成するだけです。レンダリング パス用の描画クワッドの合成は、GPU で効率的に行うことができます。これは、GPU 機能に直接マッピングされる視覚効果が慎重に選択されているためです。

ラスタライズされたタイル以外にも、描画クワッドには種類があります。たとえば、テクスチャにまったく支えられていないソリッド カラー描画クワッドや、動画やキャンバス以外のテクスチャ用のテクスチャ描画クワッドがあります。

また、コンポジタ フレームに別のコンポジタ フレームを埋め込むこともできます。たとえば、ブラウザ コンポジタは、ブラウザ UI を含むコンポジタ フレームと、レンダリング コンポジタ コンテンツが埋め込まれる空の長方形を生成します。別の例として、サイト分離 iframe があります。この埋め込みは、サーフェスを使用して行われます。

コンポジタがコンポジタ フレームを送信すると、サーフェス ID と呼ばれる識別子が伴います。これにより、他のコンポジタ フレームが参照によって埋め込むことができます。特定のサーフェス ID で送信された最新のコンポジタ フレームは、Viz によって保存されます。別のコンポジタ フレームは、後で Surface Draw クワッドを介してそれを参照できるため、Viz は描画対象を認識できます。(サーフェス描画クワッドにはサーフェス ID のみが含まれ、テクスチャは含まれません)。

中間レンダリング パス

多くのフィルタや高度なブレンドモードなど、一部の視覚効果では、2 つ以上のクワッドを中間テクスチャに描画する必要があります。次に、中間テクスチャが GPU 上の宛先バッファ(または別の中間テクスチャ)に描画され、同時に視覚効果が適用されます。これを可能にするために、コンポジタ フレームには実際にレンダリング パスのリストが含まれています。常にルート レンダリング パスがあります。ルート レンダリング パスは最後に描画され、そのデスティネーションはフレーム バッファに対応しますが、他にも存在することもあります。

「レンダリング パス」という名前については、複数のレンダリング パスが存在する可能性があります。各パスは、複数の「パス」で GPU で順番に実行する必要がありますが、1 つのパスは、単一の超並列 GPU 計算で完了できます。

集計

複数のコンポジタ フレームが Viz に送信され、一緒に画面に描画する必要があります。これは、単一の集約されたコンポジタ フレームに変換する集約フェーズによって実現されます。集約は、サーフェス描画クワッドを、指定したコンポジタ フレームで置き換えます。また、不要な中間テクスチャや画面外のコンテンツを最適化することもできます。たとえば、多くの場合、サイト分離 iframe のコンポジタ フレームは独自の中間テクスチャを必要とせず、適切な描画クワッドを介してフレーム バッファに直接描画できます。集約フェーズでは、このような最適化が検討され、個々のレンダリング コンポジタがアクセスできないグローバルな知識に基づいて適用されます。

この投稿の冒頭で取り上げた例を表すコンポジタ フレームを以下に示します。

  • foo.com/index.html サーフェス: id=0
    • レンダリング パス 0: 出力に描画します。
      • レンダリング パス描画クワッド: 3 ピクセルのぼかしで描画し、レンダリング パス 0 にクリップします。
        • レンダリング パス 1:
          • #one iframe のタイル コンテンツのクワッドを描画し、それぞれに x 位置と y 位置を指定します。
      • サーフェス描画クワッド: ID 2、スケールと平行移動変換で描画。
  • ブラウザ UI サーフェス: ID=1
    • レンダリング パス 0: 出力に描画します。
      • ブラウザ UI のクワッドを描画する(タイル表示も可能)
  • bar.com/index.html サーフェス: ID=2
    • レンダリング パス 0: 出力に描画します。
      • #two iframe のコンテンツにクワッドを描画し、それぞれに x 位置と y 位置を指定します。

イラスト: Una Kravets。