Dev Study
← ブラウザの仕組み
レッスン 4 / 6·約 9 分·第5期 ブラウザの仕組み

誰がピクセルを作るのか — Layout・Paint・Raster の分担

リクエストがアプリケーションに届くまで
  1. ブラウザURL入力今ここ
  2. DNS名前→IP
  3. ルータ経路選択
  4. ロードバランサ振り分け
  5. Nginx受け口
  6. アプリ処理
  7. DB保存

前のレッスンで公式の12段を並べました。今回はその中から Layout・Paint・Raster・Layerize の4段を取り出し、それぞれが何を出力するのかを見ます。段の名前と、その段が実際に作るものがズレている箇所があります。

まず結論

**Paint はピクセルを塗る段ではありません。** 公式の逐語は `compute a display list` — 描画命令のリストを作る段です。それを `GPU texture tiles` に変えるのは後の **Raster** 段、公式が `create pixels on-screen` と書くのは最後の **Draw** 段です。

そのラスタには **software raster と gpu raster の2モード**があると公式が明記しています。だから「GPUが描く」と一言で断定できません。同じく **`will-change` を書けばレイヤに昇格する**とも仕様は書いていません。仕様の文言は `might` / `perhaps` で、**保証しているのは stacking context と containing block の生成だけ**です。

? 読む前に予測

Chromium公式が Paint 段の説明として書いているのは、次のどれでしょうか。

当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。

抽象原理

段の名前と、その段が作るものがズレている

前のレッスンで12段を並べました。今回は、その中の4段が何を出力するのかだけを追います。名前から受ける印象と、実際の出力がズレている箇所があります。

4つの段と、その出力(公式の逐語より)表
段 公式の説明 出力されるもの
Layout 大きさと位置を決める the immutable fragment tree
Paint compute a display list display list(描画命令のリスト)
Layerize display list を合成レイヤに分割 composited layer list
Raster GPUテクスチャタイルに変換する GPU texture tiles

Paint の行を見てください。 逐語はこうです。

Paint: compute a display list that describes how to raster GPU texture tiles from the DOM.

「塗る」という名前ですが、作っているのは display list です。Chromium ソース内の paint の README はもっと直接的に書いています。

Walks the LayoutObject tree and creates a display item list.

そして、その display list が誰に渡るのか。

The primary responsibility of this directory is to convert the outputs from layout (the LayoutObject tree) to the inputs of the compositor (the cc::Layer list, which contains display items, and the associated cc::PropertyNodes).

Paint 段は、Layout の出力をコンポジタの入力に変換する段です。ピクセルは1つも作りません。

Layout の出力も、名前から想像するものとは違います。公式が挙げるのは the immutable fragment tree です。LayoutNG の解説にはこう書かれています。

While the layout object tree structure closely resembles that of the DOM tree, the fragment tree is an output of layout, not an input to it.

✓ ここまでの確認

Chromium の cc には何種類のラスタのモードがあり、それは何ですか。

具体実物

ではピクセルは誰が作るのか

display list を GPU texture tiles にするのは Raster 段です(create pixels on-screen は最後の Draw 段の説明)。ここで初めてGPUの話が出てきます——ただし、必ずGPUとは限りません。

docs/how_cc_works.md の逐語です。

TileManager is responsible for rasterizing the world of tiles. Each PictureLayer provides a set of Tiles to rasterize, where each Tile is a subrectangle of painted content at a particular scale.

そして重要な一文。

There are currently two modes of raster in cc:

  • software raster: generate software bitmaps in the raster worker

  • gpu raster: generate gpu textures by sending paint commands over the command buffer

2つのモードがあります。 software raster はラスタワーカーでソフトウェアビットマップを作り、gpu raster はコマンドバッファ経由で描画命令を送ってGPUテクスチャを作ります。

だから「レンダリングの最後はGPUが描く」という説明は、片方のモードだけを述べていることになります。

cc 自身の役割はこうまとめられています。

cc is responsible for taking painted inputs from its embedder, figuring out where and if they appear on screen, rasterizing and decoding and animating images from the painted input into gpu textures, and finally forwarding those textures on to the display compositor in the form of a compositor frame.

✓ ここまでの確認

CSS Will Change 仕様が `will-change` について「保証している」効果は何ですか。

⇄ 2つを見比べる
具体例 A

Layerize のトレードオフ

レイヤを分けるほど再ラスタは減りますが、GPUメモリを食います。公式は両極端を先に示し、その間で釣り合いを取る段だと説明します。だから「分ければ速い」という単純な規則にはなっていません。

公式が挙げる両極端(逐語の要約)表
全部を1枚に統合 スクロールのたびに高価な再ラスタが要る
chunkごとに分割 再ラスタは避けられるがGPUメモリをすぐ使い果たす
公式の方針 既定は統合。コンポジタスレッドで変化が
予想されるものだけ統合しない
具体例 B

will-change の仕様文言

事前に最適化を仕込ませるためのヒントですが、仕様は昇格を保証しません。宣言が多すぎるとGPUメモリを使い果たすため、ブラウザは昇格を避けてよい、と仕様自身が書いています。Layerize と同じ資源の制約が、仕様の側にも現れています。

仕様が使っている動詞表
might avoid doing that 昇格を「避けうる」
perhaps rendering them to their own 「おそらく」
A browser might take ... as a signal 「signalとして扱うかもしれない」
保証されるもの stacking context と
containing block の生成のみ

片方はChromiumの実装方針、もう片方はW3Cの仕様文言です。書き手も目的も違いますが、同じ慎重さが現れています。共通する構造は何でしょうか。

どちらも「最適化を増やすと何が減るのか」を考えてください。そのうえで、なぜ条件を確定させずに書いているのかを見てください。

この章のまとめ

  • Paint はピクセルを作らない。 逐語は compute a display list。README は creates a display item list と書く。
  • Layout の出力は the immutable fragment tree。 an output of layout, not an input to it と明記されている。
  • display list を GPU texture tiles にするのは Raster 段(create pixels on-screen は Draw 段)。ただし cc には software raster と gpu raster の2モードがあり、「GPUが描く」と断定できない。
  • Layerize はトレードオフ。 既定は統合し、コンポジタスレッドで変化が予想される property tree state を持つものだけ統合しない。全部分けると GPUメモリを使い果たす。
  • will-change が保証するのは stacking context と containing block の生成のみ。 昇格は might であり、仕様自身が「宣言しすぎると昇格を避けることがある」と書いている。
  • ★ 「transform はレイアウトを起こさない」は、Chromium 設計文書・仕様では裏付けも反証も取れていない。 明示しているのは web.dev の解説記事(最終更新 2015-03-20)。断定も否定もしないのが正確。
  • 60fps / 16.7ms は仕様の要求ではなく例示値。 仕様は does not mandate any particular model と明記している。
  • 公式ドキュメント自身が "draw" と “swap” というもう実態に合わない名前が残っていると認めている。名前ではなく入出力で段を理解する。

自分の現場で確かめる

読んだだけでは身につきません。手元の環境で実際に見てみてください。

理解度チェック

読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。

問題 1 / 3正解: 0

「Layout の出力は render tree である」という説明を、Chromium公式の用語に照らすとどうなりますか。

用語集(5語)
display list
Paint 段の出力。描画命令のリストであってピクセルではない。paint の README は Paint 段について `Walks the LayoutObject tree and creates a display item list.` と書いている。
the immutable fragment tree
公式が Layout の出力として挙げるもの。`the fragment tree is an output of layout, not an input to it`(LayoutNG の解説より)。
software raster / gpu raster
cc にある2つのラスタのモード。前者はラスタワーカーでソフトウェアビットマップを生成し、後者はコマンドバッファ経由で描画命令を送ってGPUテクスチャを生成する。
layer(cc における定義)
逐語は `A layer is a 2d rectangle of content with integer bounds. It has some transform, clip, and effects on it that describe how it should look on screen.`
will-change の規定上の効果
stacking context と containing block の生成のみ。それ以外は UA への rendering hint であり、レイヤ昇格は保証されない(CSS Will Change Module Level 1、W3C CRD 2022-05-05)。