MipmapとTextureStream周りの挙動によるテクスチャのメモリ周りについて纏めました。
間違ってたらごめんなさい、指摘ください。
検証UE4: 4.24.0
検証環境: windows - Developmentパッケージ
ここで取り扱う「Mip」はテクスチャのMipmapになります
結論
(いつも記事とか資料が長いと言われるので先に結論……)
-
テクスチャのサイズがフルでロードされる訳ではない。レンダリングに必要なMip分しかロードされずメモリに乗らない。(Mipなし、NeverStream除く)
- →テクスチャの最大サイズを減らしてもメモリ的には減らない可能性がある
- ただし、カメラに映った際に低解像度でボケてもいい、位まで落とすと効果はある
- →テクスチャの最大サイズを減らしてもメモリ的には減らない可能性がある
-
画面に表示されない限り、テクスチャアセットをロードしていてもメモリ的にほぼ問題にならない(Mipなし、NeverStream除く)
- →最小解像度Mip分のメモリや、ロード時間に関しては掛かる
-
3Dで出すテクスチャは極力Mip有り、NeverStream無しにしておく。メモリ節約になる
- PostProcessとかで使う等、カメラとの位置が固定されているテクスチャは逆にMip無しにすると低解像度Mip分空くかも
はじめに
UE4では、必要になった時に、必要なMipを読み込むTextureStreamという機能があります。
必要ない時は高解像度Mipをロードせずメモリを節約する形です。
こちらのスライドに分かりやすく書いてあります(10ページ位から)
→そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 - SlideShare EpicGameJapan 岡田和也
よくある誤解で、アセット見て「テクスチャ大きすぎ!」って指摘するのがある。例えば4Kテクスチャだらけのキャラでも、720pで画像くらいの大きさで描画する際に使われるテクスチャは256が殆ど。なのでオリジナルのテクスチャのサイズが4Kでもそれは描画にもメモリにも負荷にならないんよね。#UE4 pic.twitter.com/bGLOBcSQSX
— スミオ(SUMIO) (@tempkinder) February 3, 2019
TextureStreamingは、画面にレンダリングする際に必要なMipサイズが足りないと、そのMipをロードします。
(詳細な条件は省きます。時間ができたら追記するかも)
→カメラがオブジェクトに近づく
→低解像度のMipだとボケるので高解像度のMipが必要になる
→高解像度のMipをロードする
この辺りの挙動をテストしました
Mipロードの検証
そして、
のstat memory, stat streaming, タスクマネージャでのメモリの数値を計測しました
2x2のテクスチャ
元々低解像度しか用意されていないので変わらないです
4096x4096 Mip有りテクスチャ
遠い時は2x2と変わりは有りません。
近い時はおおよそstatで70MB増えています。
しかし、もしフルでテクスチャがロードされていると、4096 x 4096 x RGBA8 (x mip) x 10枚 = 700MB超のメモリが確保されるハズです。
それが70MB程度で済んでいます。
4096x4096 Never Streamテクスチャ
テクスチャの設定でNever Streamにしていますと、TextureStreamingの効果が無効化され、常にフルのテクスチャがロードされます。
距離に応じたMipが必要ないUI/HUD/2Dに使用することは有るかと思います。
カメラが遠かろうがフルでロードされています。
遠景とかですと、画面に数pxしか出ないのにMipが全部ロードされる、といった大変な事になります。
「4096x4096 Mip有りテクスチャ」版と比べてみても、かなり余分なテクスチャがロードされていることが分かります。
→逆にNeverStreamが無効で、Mipが存在していると使用テクスチャメモリはかなり削減されています。
2x2のシーンで「4096x4096 Mip有り」のテクスチャアセットをロードしている
画面に表示されてはいないけど、「4096x4096 Mip有り」を内部的にロードしている状態です。
-
こんな感じでレベルBPにテクスチャアセットの参照をつけてロードされてしまうように
-
実行後も4096x4096テクスチャのアセットがロードされているのを確認
-
カメラが遠い時
-
カメラが近い時
サイズ的には、2x2のテクスチャ+4096x4096 Mip有りテクスチャの最小値(一番遠い時のMip)がロードされているのが分かります。
ロードはされているので、最小解像度Mipが必要。
だけどカメラにアップで映される事がないので、高解像度Mipがロードされる事がない。です。
→テクスチャアセットがロードされていても、画面に表示されない限りはそこまで問題にならない、という事になるかと思います。
(NeverStreamはダメ)
Poolサイズ
このTextureStreamingには使用できるメモリ制限があります。
r.Streaming.PoolSize で定義されます。(Windowsデフォルトだと1000MBほど)
Poolサイズをオーバーすると、Mipがロードされなくなります
-
Poolサイズが足りている時
-
Poolサイズが足りない時
-
コチラが詳しいです
-
(Poolメモリは起動時にガツッと取られるのではなくて、必要になった段階で随時確保されていく感じ……?)
補足事項
- このロードしたMipは内部的にキャッシュしており、そのまま離れても破棄されない事があります。
- 下記コマンドでそのキャッシュをしないようにでき、カメラが離れてMipが不必要になるとすぐに破棄されます。
- r.Streaming.dropmips 1
- ロードされるMipは低解像度のMipから順番にロードされていきます
- 2のべき乗じゃないテクスチャはMipMapが作られず、常に再高解像度のテクスチャがメモリに乗ることになります。- Twitter @tempkinder
参考資料
- 重要[UE4] Texture Streaming Pool Sizeの決め方を考えてみる - Qiita @EGJ-Nori_Shinoyama
- [UE4] StreamingされないTextureはStreaming Texture Poolに入るのか?? - Qiita @EGJ-Nori_Shinoyama
- [UE4] Texture Streaming Pool Over Budgetの意味 - Qiita @EGJ-Nori_Shinoyama
- [UE4] Texture GroupがTexture Streamingに与える影響 - Qiita @EGJ-Nori_Shinoyama
- [UE4] TextureのNever Streamの動的変更について - Qiita @EGJ-Nori_Shinoyama
- そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 - SlideShare EpicGameJapan 岡田和也
- よくある誤解で、アセット見て「テクスチャ大きすぎ!」って指摘するのがある。例えば4Kテクスチャだらけのキャラでも、720pで画像くらいの大きさで描画する際に使われるテクスチャは256が殆ど。なのでオリジナルのテクスチャのサイズが4Kでもそれは描画にもメモリにも負荷にならないんよね。#UE4 - Twitter @tempkinder