トリプルバッファとは何か

トリプルバッファとは、フレームバッファを3つ用意して相互に切り替えながら描画を行う方式のことと言える。が、どうも2種類の利用方法が両方使われていて混乱できる。

ダブル"レンダリング"バッファ / 非同期レンダリング

一般には、tearingを避けるためのレンダリングとフリップ(実際に画面に表示するバッファのこと)の非同期化を指すことが多い気がする。

  • レンダリング用のバッファを3つ用意する
  • それぞれのバッファは2つのステートを持つ
  • ゲームは"レンダリング可能"バッファのどちらかに描き、どちらかのレンダリング可能バッファは(安定状態では)常に完成した画面を保持する

このアプローチによって、

  1. GPUは画面の途中で表示バッファを切り替える必要がない
  2. ゲームは常にレンダリングを行うことができる

の両立が可能になる。
逆に、3つもレンダリング用のバッファを用意するほどVRAMの余裕がなければ、ダブルバッファ(表示用と描画用にそれぞれ1つづつのバッファを用意する)を採用し、以下のいづれかのデメリットを受け入れる必要がある。

  • 画面の途中で表示バッファを切り替えても良いことにする(VSYNCをやめる、H-Flip)。ゲームは常に画面を描画できるが、tearingが発生する。
  • GPUが画面を表示しおわる(HDMIなり何なりでディスプレイにVRAMの内容を送信しおわる)まで待つ(VSYNCする)。ゲームエンジンの作りによっては入力遅延が発生する。
  • 画面の描画内容が表示と同じペースで完了するように負荷を調整する。面倒。

いわゆる家庭用ゲーム機では、プラットフォームのGPU性能は一定であり、60Hz/50Hz(PAL)表示を前提としているため、トリプルバッファを避けてダブルバッファ実装が選択されやすい。

フリップキュー / Swap chain / render ahead

フリップキューは、レンダリング済のフレームバッファGPU側にキューすることができる仕組みで、近い用語としてDirectXではswap chainとかrender aheadのように呼ばれる。

これも3つ(またはそれ以上)のレンダリングバッファを使用するため紛らわしい。AnandTechの記事( http://www.anandtech.com/show/2794/4 )ではワザワザ注釈を付けている。

Microsoft doesn't implement triple buffering in DirectX, they implement render ahead (from 0 to 8 frames with 3 being the default)

(別にDirectXでもアプリケーション側で前者のtriple bufferingと同様のことは実装できると思うが。。)
フリップキューが存在すると、描画済みフレームのenqueueが多少遅れても(= 60Hz間隔をたまに守れないことが有っても)フレームを落とすことが無くなる。が、常にqueueの深さの分の遅延が存在することになる。
OpenGL系のAPIはこの辺を良く抽象化していないので、移植性のある良い書き方が存在しない。ゲームはそもそもCPU/GPUをどんなに占有しても怒られないので、こちらのバッファ戦略を気にする必要は殆ど無い。