Primer 01 — Render Pipeline
1フレームの旅 / The Life of a Frame

ゲームスレッドと
レンダースレッドの流れ

ゲーム画面の1フレームは、CPU と GPU の間をリレーのように渡り歩いて作られます。「いま見えている絵」は、実はゲームロジックが計算している最新フレームより数フレーム前のものです。なぜそうなるのか、CPU の Game Thread から GPU までの流れを、図と動きで追っていきましょう。

Game Thread Render Thread RHI Thread GPU

§1 — Game Loop

まず「ゲームサイクル」から

どんなゲームも、毎フレーム同じ4つの仕事を高速で繰り返しています。入力を読み、世界を1コマ進め、その状態を絵にし、画面に出す。この繰り返しを ゲームループ(game loop)と呼びます。60fps なら、この一周を 約16.6ミリ秒で回し続けているわけです。

01
Input
入力を読む。キー・パッド・マウス・ネットワーク。
02
Update
世界を1コマ進める。Tick・物理・AI・アニメ。
03
Render
その状態を絵にする。CPUが命令を作りGPUが描く。
04
Present
完成した絵をモニタに出す (VSync)。→ 01へ戻る。
↻ これを毎フレーム繰り返す — 60fps なら 1 秒間に 60 周

素朴には「順番に4つやって1周」。でも実際のUEはこれを1本の直列処理では回していません — ここからが本題です。


§2 — The Pipeline

流れ作業(パイプライン)で回している

もし1フレームを「Update が終わってから Render、終わってから GPU」と直列でやると、その間ほかの部品は遊んでしまいます。そこで UE は工場のライン(pipeline)のようにずらして並行させます。Game Thread が今のフレームを計算している間に、Render Thread は1つ前のフレームを、GPU はさらに前のフレームを処理している ── これが「表示が数フレーム遅れる」正体です。

直列 vs パイプライン — なぜ「ずらして並行」なのか
Game Render RHI GPU
直列でやると(naive)
G0
R0
H0
P0
G1
R1
H1
P1

1フレーム完成までフル4コマ。その間ほかの部品は遊んでいる → スループットが上がらない

パイプラインなら(UEはこちら)
F0
F1
F2
F3
F4
F0
F1
F2
F3
F0
F1
F2
F0
F1

段が埋まれば 毎コマ1フレームずつ完成(スループット約4倍)。ただし最初の1枚が出るまで数コマ待つ ── この待ち分が「フレーム遅延」の正体です。

時間 → (同じ色 = 同じフレームの旅)
NOW
再生すると、いま各スレッドがどのフレームを処理しているかが表示されます。

NOWの縦線を各段が下りていくのが1フレームの旅。同じ瞬間でも、下の段ほど「古いフレーム」を扱っています。(この図は分かりやすさ優先で1段=1フレーム遅延。実機のUEはRender/GPUが重なり、体感遅延はおよそ2フレームです)


§3 — Who does what

各スレッドの役割

4つは一方向のバトンリレーで動きます。前の段が作った成果物を、次の段が受け取って別の形に変換していく流れです。

CPU
Game
Thread
世界を1コマ
進める
描画命令
render cmds
CPU
Render
Thread
描く段取りを
組む
RHIコマンド
RHI cmds
CPU
RHI
Thread
GPUへの
通訳
APIコール
submit
Hardware
GPU
実際に
塗る
ピクセル
present
Monitor
画面表示
1フレーム
完成

矢印の上が「次の段へ渡す成果物」。前段の出力が次段の入力になり、少しずつGPUが分かる形へ翻訳されていきます。

下のカードをクリックすると、各担当の詳しい説明が開きます。


    §4 — Bottleneck

    fps を決めるのは「一番遅い段」

    3つの段が並行して走るので、フレームにかかる時間は3つの合計ではなく最大値で決まります。スライダーで各段の処理時間を変えて、どこがボトルネックになるか確かめてみてください。「GPUバウンド」「ゲームスレッドバウンド」という言葉はこれを指します。

    16.6 ms (60fps)
    Frame Time
    実効 fps
    結果


    §5 — Screen Capture

    画面をキャプチャしたいとき

    「今の画面を保存したい」— これは思ったより一手間かかります。絵は GPU 側のメモリ(Render Target)にあり、CPU から直接は読めません。GPU に「CPUが読める場所へコピーして」と頼み、それが終わるのをフェンス(fence)で待ってから読み出します。ステップをクリックすると詳細が開きます。

    メモリの地図 — なぜ一手間かかるか
    GPU側メモリ · VRAM
    Render Target
    描いた絵(テクスチャ)
    CPU ⇄ GPU
    メモリ境界
    コピー+
    Fenceで完了待ち
    システムメモリ · CPUが読める
    Readback バッファ
    → Map → TArray<FColor> → PNG

    CPU は VRAM を直接読めません。だから「コピーして・待って・読む」の3手間になります。下の5ステップはこの地図を時間順に並べたものです。

    要点:読み取れるのは GPU が今出した絵 = ゲームスレッドより数フレーム前の状態。ReadPixels のように「今すぐ待って読む」とパイプラインが止まり (flush)、カクつきの原因になります。UE の高解像度スクリーンショットや SceneCaptureComponent2D は、この流れを裏でやっています。


    Glossary — 用語

    よく出る言葉