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 つあります。2 つは foo.com のレンダリング プロセスにあり、1 つは bar.com のレンダリング プロセスにあります。

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)
  • (Box <span>, 1)
  • (テキスト「Hi」、0)
  • (線のボックス、3)
  • (ボックス <b>、1)
  • (テキスト「there」、0)
  • (テキスト「.」、0)

このデータ構造を使用するコンシューマは、ユーザー補助 API、getClientRectscontenteditable などのジオメトリ API など、多数あります。それぞれ要件が異なります。これらのコンポーネントは、便利なカーソルを介してフラット データ構造にアクセスします。

カーソルには、MoveToNextMoveToNextLineCursorForChildren などの API があります。このカーソルの表現は、次のような理由からテキスト コンテンツに非常に強力です。

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

プロパティ ツリー

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

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

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

プロパティ ツリーは、視覚的効果やスクロール効果が DOM 要素にどのように適用されるかを説明するデータ構造です。たとえば、特定の DOM 要素が、所定のレイアウト サイズと位置で示されているのは、画面に対する相対位置で、また、ビジュアル エフェクトとスクロール エフェクトを適用するために、どのような順序で GPU オペレーションを使用すればよいですか?

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

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

RenderingNG では、次のような多くの目的でプロパティ ツリーを使用します。

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

すべてのウェブドキュメントには、transform、clip、effect、scroll の 4 つの個別のプロパティ ツリーがあります。(*)transform ツリーは 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: サイズ 80x18、位置 8,8、色は緑。 drawTextBlob(位置 8,8、テキスト「Hello world」)。

ディスプレイ アイテムのリストは後ろから前に並べられます。上の例では、DOM 順序では緑色の div が青色の div の前にありますが、CSS ペイント順序では、負の z-index の青色の div が緑色の div の前にペイントされます(ステップ 3)(ステップ 4.1)。ディスプレイ アイテムは、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>

これにより、次の表示リストが生成されます。各セルが表示アイテムです。

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

ディスプレイ アイテム リストは保存され、後続の更新で再利用されます。ペイントツリー ウォーク中にレイアウト オブジェクトが変更されていない場合、そのディスプレイ アイテムは前のリストからコピーされます。追加の最適化は、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>

これにより、次の表示リストが生成されます。各セルが表示アイテムです。

ビューの背景 #scrollのバックグラウンド #scroll インライン テキスト #orangeのバックグラウンド #orange インライン テキスト
サイズが 800x600 で色が白の drawRect drawRect: サイズ 100x100、位置 0,0、色ピンク。 drawTextBlob(位置 0,0、テキスト「Hello world」)。 drawRect: サイズ 75x200、位置 0,0、色オレンジ。 drawTextBlob(位置 0,0、テキスト「I'm falling」)。

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

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

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

上記の例では、理想的には 2 つの合成レイヤが生成されます。

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

ユーザーが #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 によって保存されます。別のコンポジタ フレームは、後でサーフェス描画四角形を介してそのフレームを参照できるため、Viz は描画する内容を把握できます。(サーフェス描画クワッドにはサーフェス ID のみが含まれ、テクスチャは含まれません)。

中間レンダリング パス

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

「レンダリング パス」という名前については、複数のレンダリング パスが存在する可能性があります。各パスは GPU で複数の「パス」で順番に実行する必要がありますが、単一のパスでは単一の超並列 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