イベント
[GTC 2015]NVIDIAが発表したVR向けSDK「VR Direct」は,AMDの「LiquidVR」と一体何が異なるのか
そうしたVRコンテンツ開発者に向けて,VRコンテンツ開発に必要な基本的な機能をライブラリやソフトウェア開発キット(以下,SDK),APIの形で提供していこうという動きが立ち上がっている。そのひとつが,GDC 2015に合わせてAMDが発表したVRコンテンツ開発用SDK「LiquidVR」だ。
一方,競合であるNVIDIAも同様に,「VR Direct」というVRコンテンツ開発用SDKを発表している。VR Directとは,VRコンテンツの映像描画において,NVIDIA製GPUの性能をフルに活用できるようにするためのSDKやAPIの総称だ。
GTC 2015では,このVR Directに関する技術解説セッション「VR Direct: How NVIDIA Technology is Improving the VR Experience」が行われたので,その概要をレポートしよう。講演を担当したのは,NVIDIAにてDeveloper Technology Engineerを務めるNathan Reed氏だ。
VRコンテンツにおける表示遅延対策の基本
フレームキューイングの無効化とタイムワープ
VR体験において,最も気を付けなければならないのは,HMDをつけた頭部の動きに対して映像の表示が遅れる表示遅延(レイテンシ)の問題だ。
一般的なPC上の3Dゲームグラフィックスでは,CPUとGPUとがそれぞれ最大のパフォーマンスを発揮できるように,Frame Queuing(フレームキューイング)という仕組みを導入して,CPUとGPUの並列動作性を高めようと工夫している。
GPUは,CPUから転送された描画コマンド列で駆動されるわけだが,この描画コマンド列を組み立てるのはCPUの仕事だ。CPUは各フレーム単位のゲーム処理と描画コマンドを生成し,GPUはその描画コマンドをもとに各フレームを描画する。だが,それぞれの処理が必ずしも決められたフレームレートを実現するのに必要な時間内に終われるとは限らない。そこで,不揃いな処理時間を平均化しつつ,CPUとGPUをフル可動させるための手法がフレームキューイングの考え方で,Reed氏はこれを,いわゆる「バックバッファリングと実質的に同じもの」だとして説明を続ける。
DirectXではバックバッファの数として,デフォルト値では「3」が設定されている。しかし,バックバッファが3ということは,入力が処理されて映像が表示されるまで3フレームの遅延が確実に生じてしまうわけだ。
普通のゲームでも十分問題だが,VRコンテンツでは3D酔いをもたらす原因にもなるので,ユーザー側の入力や頭部移動を含めたインタラクション処理に対する遅延は,少なければ少ないほどいい。そうなると,フレームキューイングはキャンセルする必要が出てくる。
Oculus VRがVR対応HMD「Rift」用SDKでは,フレームキューイングがデフォルトでキャンセルされているのだが,DirectXではコンテンツ開発者が「IDX
フレームキューイングのキャンセルによって,レンダリングパイプライン上の遅延は最低限にできるが,ほかにもVR対応HMDならではの問題もある。ユーザーが連続的に首を動かしていると,描画開始前に判定した頭部の向きと,描画完了時の向きが変わってしまう場合があるのだ。この状態で映像をそのまま表示したのでは,HMD上に遅延した表示が行われてしまう。
ここで,(物理的に正確ではないのだが)描画された映像を頭部の向きに対応する位置に表示すれば,頭部の動きに対してつじつまが合っているかのような映像表示が行える。たとえば,右を見回すように首を動かし続けているのなら,映像描画後には首の回転角度分だけ映像を左側にずらしてHMD上に表示するのだ。映像が左にスクロールしているようなものだから,首の回転方向――右回転なら視界の右端――には未表示部分が出てくるのだが,ごくわずかな時間と量なのでほとんど気づかれることはないとReed氏は説明する。
こうした処理のことを,Oculus VRは「Time Warp」(タイムワープ)と呼んでおり,VR業界でもこの呼び方が浸透しつつある。ただ,タイムワープ処理だけで,動きへの追従は万事問題なしというわけではない。なにしろ,頭部が本当に向いている方向に対応した正確な映像ではないし,ゲーム処理との矛盾が起きる可能性もあるからだ。とくに,GPUによる描画が長引いて垂直同期(Vsync)に間に合わないような場合は,別の対処法を考えなくてはならない。
描画がVsyncに間に合わないときに,タイムワープはどう処理するべきか
VRコンテンツにおけるグラフィックス描画のパイプラインを整理すると,以下のような流れになる。
- 頭部の向きを検出
- GPUでの映像描画
- 頭部の向きを再検出
- タイムワープ処理
「映像表示はVsyncに合わせて行わなければならない」のが鉄則なので,描画が長引いてVsyncを逃してしまうと,せっかく描画し終わった映像の表示タイミングも逃してしまい,コマ落ちとなって映像のカク付き(Stutter)を起こしてしまう。VRコンテンツでは,最低でも毎秒60コマ(60fps),Oculus VRのRiftでは毎秒90コマ(90fps)のフレームレートが求められているため,よほど高性能なGPUでないと,現実問題としてこの条件を守るのは難しい。
そこで,Vsyncのタイミングに間に合わない場合のことを考えなければならなくないと,Reed氏は指摘する。
その実装が現実的か否かは別にして,Reed氏は2とおりの対処方法を掲げた。そのひとつは,空間的多重化法(Space Multiplexing)を用いた手法だ。
60fpsにおける1フレーム分の時間は16.67ms。この16.67msを10個のサブフレームに区切った場合,サブフレーム1つ分は16.67msの10分の1である1.667msとなる。
そこで描画開始時は,その時点における頭部の向きで3Dオブジェクトを描画しておく。そして,サブフレーム1つ分にあたる1.667ms後には,1.667ms分のタイムワープ処理を加えた位置に3Dオブジェクトを描画するのだ。そして,1.667msが経過するごとに,次のVsyncが来るまで同じ処理を繰り返す。これが空間的多重化法による描画の概念だ。
話を聞いていると,なんとなくうまくいきそうな気もする。だが,Reed氏は「グラフィックスを描いているそばから連続的に表示していけるようなディスプレイ装置ならば適合するかもしれない。だが,映像を表示するタイミングがVsyncごとという現在のディスプレイ装置(※VR対応型HMDもそうだ)では適合しにくい」という。
もう1つの手法は,時間多重化法(Time Multiplexing)だ。
こちらはGPUをフルに使って映像の描画を実行しつつ,定期的にやってくるVsyncタイミングの直前に,描画を終えた映像に対してGPUでタイムワープ処理を適用していくという考え方である。
そして,現在進行中の描画が終わりきっていない場合は,現在表示中の前フレームに対してタイムワープ処理を適用するというのがポイントだ。映像内容は前フレームと変わらないのだが,タイムワープ処理が適用されて時間軸上のつじつまが合わされることで,明らかなカク付き(≒遅延の露呈)が顕在化するよりはマシな表現ができるという理屈だ。
そして,遅れていたフレームの描画がVsync後に完了すると,これにタイムワープ処理を施したうえで,いわゆるVsync無効状態のように表示してしまうという。
Vsync無効状態の表示なのだから,いわゆるテアリングが生じてもおかしくない状況だが,タイムワープ処理を加えた同一時間軸上の映像になっているので,テアリングは最低限で目立たない。映像の動きが小さい背景などでは,テアリングはほとんど知覚されないだろうし,見えるとしても大きく動いている部分,たとえば目前でこちらに向かって剣を振り下ろしている戦士の腕やその剣先くらいのはずである。
Reed氏によると,NVIDIAのVR Directでは,この時間多重化法をタイムワープ処理に採用したとのことだ。映像の描画とは非同期にタイムワープ処理を行うメカニズムなので,名称は「Asynchronous Timewarp」(非同期タイムワープ処理)と呼ぶ。
さて,実のところこの仕組みは,AMDのLiquidVRが採用したものとほとんど同じで,呼び名も同じだ。
NVIDIAとAMD,どちらが最初にこの手法を採用したのかは分からないが,おそらくOculus VRから両社に対して,「こうしたタイムワープ仕様を実装してくれ」というリクエストがあり,それを両社が実装した結果こうなった,というあたりが真相ではないだろうか。
Reed氏も実際,「この機能はOculus VRからのリクエストを受けて実装された」とコメントしていたことからも,まず間違いないだろう。
AMDとNVIDIAで異なる非同期タイムワープ処理の実装手法
興味深い点は,NVIDIAのVR DirectとAMDのLiquidVRで,時間多重化法によるタイムワープ処理の実装手法が異なっているところだ。
LiquidVRでの実装手法は,GDC 2015のレポート記事で詳しく説明しているので,そちらを参照してほしいが,簡単にいうとLiquidVRでは,AMDのGCNコア系Radeonに搭載されているグラフィックス描画タスクとGPGPUタスクを同時並列に動かせる機構を活用して,映像描画はグラフィックス描画タスクで,タイムワープ処理はGPGPUタスクで処理している。
一方,NVIDIA製GPUは,グラフィックス描画タスクとGPGPUタスクを同時に実行できないという制約がある。これは最新のMaxwellアーキテクチャでも同じで,モードチェンジをしてグラフィックス描画タスクとGPGPUタスクを切り換えないと,それぞれのタスクを実行できないのだ。すなわち,AMDのLiquidVR的なアプローチは使えない。
そこで,NVIDIAのVR Directでは,GPGPUタスクを活用する方法は採用せずに,グラフィックスレンダリングモードのまま映像描画タスクとタイムワープ処理タスクを走らせる方法を考え出した。
まず映像描画タスクは,普通にシーン描画をマイペースにやらせておく。一方,同じグラフィックスレンダリングモード内で,Vsyncのタイミングが近づいてきたら,優先度の高いタイムワープ処理タスクを起動してやるのだ。すると,
起動されたタイムワープ処理タスクは,フロントバッファにある映像に対して,頭部の向き状態を反映したタイムワープ処理を行う。前のフレームが表示されたままであれば,そのフレームに対してタイムワープ処理を行い,次のフレームが描画済みであれば,そのフレームに対してタイムワープ処理を行って表示するというわけだ。
ところで,このタイムワープ処理の起動には「High-Priority Context」と呼ばれる機能が使われているという。これは,その時点でGPUが行っているタスクを中断してでも,起動させられたその新しいタスクを優先して実行する機能で,この仕組みを使ってタイムワープ処理を起動するわけである。
ただしタスク切り替えは,その時点でGPUが処理中の描画コマンドが実行完了したタイミングでしか行えない。これはNVIDIA製GPUにおける現時点での制約で,もし長い描画コマンド列を実行していたりすると,タイムワープ処理の起動が待たされてしまうので,想定したタイミングで処理できなくなる局面も起こりうる。
Reed氏は,将来世代のGPUでは描画コマンド実行中の任意のタイミングで行えるような,粒度の高いタスク切り替え機能が実装されるはずである,と述べていた。
ちなみに,NVIDIAのGPUの隠し機能だったHigh-Priority Context機能は,現在リリース済みのドライバソフトで利用できるそうで,DirectX,OpenGLのどちらでも利用可能とのこと。さらに,SoC(System-on-a-Chip)の「Tegra K1」や「Tegra X1」でも利用できるとのことだった。
Reed氏はここまで説明したうえで,コンテンツ開発者に注意もうながしている。いわく,「非同期タイムワープ処理はあくまで,最悪の事態を回避するための保険的メカニズム」であり,積極的に頼ることはせず,可能な限り映像描画をVsyncに間に合うように設計すべきだということだ。
また,非同期タイムワープ処理はHigh-Priority Context機能によるタスク切り替えに依存している以上,この切り替えが描画コマンド終了のタイミングでしか行えないことを踏まえて,描画コマンドが定期的に終了するようなレンダリングエンジンにすべきである,とも述べていた。具体的には「1msごとに(描画コマンドが)終わるといい」(Reed氏)ということだった。
とはいえ,定期的に描画コマンドが終了できるような設計にするのは,現実問題として難しい。たとえば,タイル単位で描画コマンドが終わる「タイルベースレンダリング」を採用するゲームエンジンであれば,この条件に適合させやすいかもしれない。
VRコンテンツでマルチGPUを活用する技術「VR SLI」
AMDのLiquidVRには,マルチGPUをVRコンテンツの映像描画時に効率よく活用するための機能「Affinity multi-GPU」という機能が搭載されていた。NVIDIAのVR Directにおいてそれに当たる機能が「VR SLI」だ。
Affinity multi-GPUと比較して,機能や実装面にはたいした差がなかったので,詳細はLiquidVRの記事を参照してもらうとして,ここでは簡単にまとめておこう。
2Dコンテンツ(ゲームもそうだ)の映像描画において,最も有効なマルチGPUの活用方法は,複数のGPUがそれぞれ1フレーム分の映像をレンダリングする「Alternative Frame Rendering」(以下,AFR)方式だとされてきた。偶数フレームをGPU0,奇数フレームをGPU1に描画させるといったお馴染みのやり方だ。
しかし,VRコンテンツでは遅延をできるだけ排除したいので,1つのフレームを極力早く描画したいという需要がある。そこで,GPU0を左目側,GPU1を右目側というように,左右それぞれの映像描画にGPUを1基ずつ割り当てて描画させるという手法が考えられた。
ただ,左右それぞれの映像は,同一シーンを同じタイミングで2視点から見ているだけなので,描画すべきシーン情報は2基のGPUで共通だ。そこで用意されたのが,描画したいシーンの情報と両目の位置や向きだけを伝えれば,自動的に2基のGPUに対して両目の映像描画を仕掛けるというのが,VR SLIの本質的な機能である。
CryENGINEはVR Directにも対応
Pradel氏の説明によると,VR DirectとLiquidVRでは若干機能の実装方法に違いはあったそうだが,最終的にはほぼ同一の機能を提供できるようだ。つまり,
筆者が把握している限りでは,ほぼすべてのメジャーなゲームエンジンは,LiquidVRとVR Directの両方に対応する見込みだ。ゲームエンジンを活用してVRコンテンツを開発する限り,これらの違いを意識する必要はなさそうで,開発者にとっては朗報といえるだろう。
VRコンテンツ産業はまだ十分に立ち上がっておらず,VR対応ハードウェアやVRコンテンツの開発側も活動実体像が不明瞭。また,ハードとソフト両面におけるノウハウも蓄積されていないので,今の時点でAPI仕様を策定しても意味がないだろう,とのことであった。Imagination Technologiesが提唱したプログラマブルレイトレーシングAPIの「OpenRT」が,オープンスタンダード化するには時期尚早と判断されたことと同じ理由であった。
何かとあちこちから熱気が伝わってくるVRではあるが,まだ産業としては黎明期なのである。
NVIDIA公式Webサイト(英語)
GTC公式Webサイト(英語)
- この記事のURL: