Sampler Feedback Streaming の威力が如何にものすごいかについて

立て続けにゲームハードウェアに関する考察です。
今回は Series X|S の密かな技術革新、Sampler Feedback Streaming (SFS) について。

SFS が如何にスゲーか、の考察に入る前に、2つの技術要素についてまず考察します。

その1:Texture Streaming

昨今、ゲームはいよいよ高解像度化し、次世代では True 4K が一つの大きな柱となります。
しかし、一口に4Kと言っても、ジオメトリを4K解像度レンダリングすることはエッジの精細さにおいて重要ですが、仮にそこに2Kのテクスチャを適用すれば、画面のほぼ大半を占める「エッジ以外のサーフェース」は、結局2Kレベルの情報量にとどまってしまいます。(PS4 Pro の4Kはこの状態でした)
したがって、4K時代にはテクスチャの解像度も4Kであることが必要です。4Kテクスチャは2Kテクスチャに比べて4倍のサイズとなり、1枚で8MBのメモリを使用します。シーンに必要なテクスチャの枚数は据え置いたとしても4倍サイズとなると、PS4/Xbox One世代の8GBメモリから次世代で16GBと倍になっても、まるで足りねえということになります。つまり、テクスチャをそのまんま全部メモリに格納するのは、効率が悪い。

テクスチャマップがミップマップされているのは今般既に常識として、Mipレベルを1つ上げるごとに容量は1/4になり、通常、最も詳細な (4K解像度の) Mipレベル0が必要なのは最も手前のオブジェクトだけで、中距離~遠景のテクスチャはもっとMipレベルの高いものが参照されます。
つまり、中距離~遠景のオブジェクト用のテクスチャを4K解像度のままメモリにロードしても、ほとんど無駄になってしまうということです。
この無駄を削減するには、シーンに必要なMipレベル以上のデータ(これを部分Mipチェーンと呼びましょう)だけをメモリにロードすればよく、さらに詳細なMipレベルのデータが必要になった時点で、ロードしなおせばよいという効率化が考えられます。
これら一連の処理が、テクスチャストリーミングです。

テクスチャストリーミング自体は、別段次世代の技術ではなく、PS4/Xbox One 世代でも Unreal Engine 4 などで機能提供されていて普通に使われています。

https://docs.unrealengine.com/ja/Engine/Content/Types/Textures/Streaming/index.html

が、UE採用タイトルで、シーンの切り替わり直後などに一部のオブジェクトのテクスチャが荒く、徐々に詳細なテクスチャに置き換えられる、という現象を見たことがあると思います。(テクスチャがポップインするなどと言われますね)
あれは「必要なMipレベルの決定」をソフトウェア制御で行っているために、シーンの変化に応じてすぐに最適化しきれていないのが可視化されているわけです。
で、荒いレベルから徐々に詳細なレベルに移り変わるということは、逆もしかりで、もう詳細レベルが不要になったものも、荒いレベルに置き換えられるまでメモリに残留するということになります。

※話は変わりますが、アセット制作においては想定する最高解像度でテクスチャを作成しておけば、上記のしくみで1080pターゲットの場合でも「アセットを作り分ける必要なく」かつ「実行時に無駄なメモリリソースを使ってパフォーマンスが無駄に劣化することなく」動作することがお分かりいただけると思います。〇〇が足を引っ張る!とか言い張っていた方々は、こういう現行世代で普通に使われている技術をご存じないんだと思います(笑)

その2:Tiled Resource

テクスチャストリーミングは必要なMipレベルのテクスチャを選択的にロードする仕組みですが、別のオブジェクトに遮蔽されたり、オブジェクトの裏側部分のテクスチャなど、1枚のテクスチャの中にも描画に必要なものと必要でないものがあります。
MicrosoftXbox One X に特別なHWを追加して「実際に参照されたテクスチャデータ」の統計を取ったところ、ロードしたうちの1/3以下しか参照しないケースが多かったということが判明したそうです。
Tiled Resource は、ミップマップを含むテクスチャを例えば8x8の64個の小さなタイルに分割して、描画時に必要な「各Mipレベル」の「各タイル」だけを組み合わせたものをメモリ(VRAM)に格納し実際の描画にはこちらを使用することで、メモリをさらに効率化するしくみです。
PCであれば、通常は追加で詳細テクスチャの読み込みが必要になった場合は、必要な Mip レベル以下をまるっとメインメモリから転送する必要がありますが、タイル化することで、詳細Mipレベルのうち本当に必要な部分のみに限って転送すればよく、効率化できるようになるわけです。
また、元のテクスチャとの対応は下記の図のように、タイルごとのメインメモリとVRAMとの変換テーブルを介しており、必要なタイルのみをメインメモリから簡単に転送できるようになっています。
https://www.4gamer.net/games/135/G013536/20120106063/SS/006.jpg

※若干話がジャンプしますが、Xbox Series X|S の場合は UMA なのでメインメモリとビデオメモリ間での転送は不要ですが、元のテクスチャをメモリ上に置いていては意味がないので、おそらくこの部分が「仮想メモリとしてメモリマップされたSSD」との変換テーブルとなり、タイル単位で必要なデータのみSSDからロードする形になるものと思われます。(PCのDX12Uでは、タイルをHDDからロードすることもできる)

ここまでの2つの機能は、DX12 アプリケーションであれば、Sampler Feedback がなくても利用可能です。
また、CheckAccessFullyMapped オプションをつけることで、タイリングしたテクスチャに残留しているテクスチャを検知してより最適化することもできるそうです。

ただ、これはソフトウェアでの制御になるため、より積極的に「最適なMipレベルの必要なタイルだけをロードする」ようにするためには、それらを特定するための追加の処理コストがかかるということになります。
また、ミップマップのどのMipレベルから実際にテクスチャをサンプルするかはGPUの処理内で決定されるので、ゲームアプリケーション側からはそれを知ることが難しく、通常はレンダーターゲットの大きさとオブジェクトの奥行きに応じて、「推測で」部分Mipチェーンを生成するしかなかった。
ましてや、テクスチャのどの部分が実際にサンプルされたか (必要なテクスチャタイルを決定する)、についてはさらに推測が難しく、推測するにもGPUコストがもっとかかるので、Tiled Resource については、実は CGN1.0 の世代 (2012年ごろ) から導入された技術にもかかわらず、ほとんど活用されてきませんでした。

実際、Unreal Engine でも、先ほどのテクスチャストリーミングにタイル分割を組み合わせた Streaming Virtual Texturing という機能があります。

https://docs.unrealengine.com/ja/Engine/Rendering/VirtualTexturing/Streaming/index.html

ただし、ソフトウェア処理なので、↑のドキュメントにも書いてあるように、
必要なテクスチャタイルを決定するために「可視性は標準の深度バッファを使用して GPU で計算」される必要があるために、「常に、仮想テクスチャは従来のテクスチャサンプルよりも負荷がかかります。常に、少なくとも 2 回のテクスチャのフェッチと、ある程度の計算命令が発生します。ただし、その負荷の一部は、同じ UV とサンプラーソースを使う VT テクスチャサンプルのスタック (最大8個) をまとめることで削減できます。 」というオーバーヘッドが生じます。
要するに、メモリ効率は良くなるけど、その代わり追加のGPUコストがかかるということです。

ここでようやく、Sampler Feedback の出番となります。

SFSは、DX12と対応GPUの組み合わせで、実際にGPU側でサンプリングされたテクスチャのMipレベルと位置情報をフィードバックすることで上記2つの仕組みのオーバーヘッドを解消し、「1ステップで理想のMipレベルと対象タイルを検出してFeedback Map に書き出す」プロセスを、GPUドライバレベルで最適化することができるのです。(つまり、ゲーム側でソフトウェア的に検知/推測する必要がないということ!)

これがすなわち、Sampler Feedback 付きの Texture Streaming、縮めて Sampler Feedback Streaming なのであります。
SFSでは実際に、前フレームでのテクスチャサンプリング情報をもとに、1フレームの遅延で最適なMipレベルと必要なテクスチャタイルを特定することが可能です。
したがって、目に見えるようなテクスチャのポップインは起きないし、理論値に近いテクスチャメモリの効率化が行えます。

で、実際に SFS を適用しますと、普通にテクスチャをロードするのに比べて、実際のゲームアプリケーションのワークロードでメモリ利用効率が2.5~3.5倍になり、メモリ使用量は3~4割で済むとのことです。
少々古いですが、バイオハザード5でビデオメモリの6~7割がテクスチャ予算に割り当てられたということなので、Xbox Series S で当てはめてみると、10GBのうちゲーム部分が8GBとし、ざっくり半分の4GBをGPU用メモリとしましょう。
このケースでは、4GB中6割のテクスチャメモリは生では2.4GBですが、SFS を適用して1/3の部分読み込みで済めば800MBで事足りるということになります。
(ちょうどこの瞬間くらい https://youtu.be/fYtJWIxt3-M?t=173 )
https://i.gyazo.com/eddb3e329a4ee96fdaa67c0cdf91936b.jpg

逆に、2.4GBにフルにテクスチャを詰め込むとすれば、利用効率3倍と考えて、7.2GBの生のテクスチャメモリ相当となる。
これは、物理搭載メモリ16GBとしてGPUに8GB、そのうち6割がテクスチャとした場合の 4.8GB よりも多いテクスチャメモリ予算となります。

16GB搭載したマシンで普通にテクスチャをロードしたのと同じクオリティを、SFS ありでは10GBメモリで十分実現できるということになりますし、となれば実際に16GBのメモリを搭載しているマシンでは…言わなくても分かりますね。

また、実質800MBをロードすればよいのであれば、Xbox Series S|X の SSD の 2.4GB/sec(RAW) という読み込み性能で計算すると、BCPack 圧縮によりテクスチャが50%に圧縮されているとして、圧縮状態で400MBの readで 済むため、0.16秒でロード可能となります。(これは60fpsであれば10フレーム相当)
実際には、シーンが大きく変わらない限りは全てのタイルを読み直す必要はないはずで、「全てのテクスチャタイルをSSD (上の仮想メモリ) から読み込む」というケースを考えた場合でも、60fpsの場合で1フレームごとに800MBのうち1割をロードしなおすことができます。(1タイル64KBになるようにタイル分割した場合で、1250タイル)

https://youtu.be/fYtJWIxt3-M?t=179

上記のデモでテクスチャタイルの状態が可視化されていますが、これを見てもタイルの読み込み直しは「目で追える」レベルなので、毎フレームごとに1割も読み直すことはほぼ起きえないと思います。
(めっちゃ速い移動みたいなシーンで追いつかない可能性はありますが、そんなスピードで画面が流れていたら普通はモーションブラーをかけてテクスチャのディティールは潰れますし、かけなくたってほぼ目で追うことはできないと思われます)

さて、ここまでで、Sampler Feedback Streaming が想定通りの威力を発揮すれば、大量の物理メモリを積まなくても、十分な品質のテクスチャをSSDからストリーミングできるということが分かると思います。
(Series S に限らず、PS5 や Series X の 16GB というメモリも今のゲーミングPCの実情からするとけっこう少な目なんですが、"SSDからのストリーミングで十分いけるのでメモリはそんなに大量じゃなくていい" というのが次世代の共通思想なんだと思います)

また、速度面に着目すれば、PS5 では Kraken で圧縮されたデータの前提で、実効8GB/sのreadとなり、この前提で仮にテクスチャデータ8GB分の読み込み時間はちょうど1秒となります。
一方、XSS|XではテクスチャをBCPackで圧縮した前提で実効4.8GB/sのreadとなり、8GBそのものを読み込む場合は1.67秒かかる計算となるが、ここでSFSにより効率が2.5倍になるとすれば3.2GBのロードでよく、この場合の読み込み時間は0.67秒となります。仮に効率が下がったとしても、1.6倍の効率まで落ちて読み込み1秒です。

実際には、PS5 においても先ほど挙げた Unreal Engine の Streaming Virtual Texturing のようなソフトウェアベースのテクスチャロード効率化テクニックを使うことはできます。
しかし、SFSのキモは繰り返しますがこの「可視テクスチャタイルの特定」オーバーヘッドをハードウェア側(GPU)でほぼ追加コストなしに実行できる (フィードバックするしないに関わらず、Mipレベルの決定とテクスチャの特定位置からのサンプルは当然ながら GPU が行うので、あとは Feedback Map の更新のコストだけで) ために、理論値に近い効率かつ、通常1~2フレームの遅延でゲーム側が「本当に必要なテクスチャタイル」を検出できるという部分にあります。

同じAMDのRDNA世代なので、もしかするとサンプラーフィードバックの機能自体はPS5のGPUにも搭載されている可能性がありますが、グラフィックスAPIGPUハードウェアの組み合わせでこれを行うという仕組みについては Microsoft が特許を抑えているらしいので、HWベースで同じことを行うのは、ひょっとすると難しいかもしれません。
あるいは、同じRDNA世代でもPS5のGPUは Primitive Shader をサポートし、Series X|S では Mesh Shader をサポートするという違いもあるので、そもそもサポートしていないかもしれません。
また、Sampler Feedback Streaming はあくまでテクスチャに関する技術なので、昨今のゲームにおいてテクスチャ容量がとにかく肥大しているためにますます有効になる技術ではあるのですが、当然、テクスチャ以外のロードに関しては効かないため、8GB/secと4.8GB/secというI/O性能の差はそれ以外の部分には出てくるものと思われます。
この辺は、実際に両ハードが発売されてからのお楽しみというところでしょうか。

なお、DirectX12の機能なので、PCでも対応しているGPU (現時点では Turing 世代の GeForce) との組み合わせで利用できます。

というわけで、PS5 の超高速SSDとの差を埋めつつ、Series S のメモリ搭載量の少なさもカバーしてくれるかもしれない、Streaming Feedback Sampler についての考察でした。