60K Views
October 07, 19
スライド概要
補足:LRUキャッシュの導入を検討する際は OpenGL.UseEmulatedUBsの有効化も合わせてご検討ください。
講演動画:https://youtu.be/A_l65FlY25I
Part 2:https://www.slideshare.net/EpicGamesJapan/ue4-festeast2019-ue4mobilepart2-179705328
2019年10月6日に行われた「UNREAL FEST EAST 2019」で登壇した際に使用した資料です。
●公式サイト
https://unrealengine.jp/unrealfest/
===
シェーダコンパイルによるカクツキなどモバイルゲーム開発特有の問題は数多くあり、それらはユーザのストレスに繋がる可能性があります。UE4はそういった問題に対しての機能を持っていますが、用法・用量を守って正しく使わないと別の問題を引き起こしてしまいます。そこで本講演ではそれらの機能の使い方、注意点などについて解説します(他のプラットフォーム開発でも役立つ内容にする予定です)。あ、今年は1人講演です。
Unreal Engineを開発・提供しているエピック ゲームズ ジャパンによる公式アカウントです。 勉強会や配信などで行った講演資料を公開しています。 公式サイトはこちら https://www.unrealengine.com/ja/
そう、UE4ならね。 あなたのモバイルゲームをより快適にする 沢山の冴えたやり方について Part1 Epic Games Japan Support Engineer 岡田和也
本日のハッシュタグ #ue4fest スライドは近日公開予定 しました
本スライド、300ページ超えだったせいなのか Slideshareへのアップに失敗しました /(^o^)\ そのため、Part1, 2に分割しています Part 2のURLに関しましては Slideshareの説明文をご確認ください
自己紹介 Epic Games Japan サポートエンジニア 岡田 和也 Twitter: おかず ( @pafuhana1213 ) ライセンシのサポート業務や講演が主なお仕事 モバイル担当してます 最近
国内のUE4モバイルタイトル 増えてきました…!
国内のUE4製モバイルタイトル
New! VARIOUS DAYLIFE(バリアスデイライフ) Apple Arcade にて 絶賛配信中!
UE4モバイルタイトルに携わる人向けに より実践的な話をせねば…!
これまでのUE4モバイルに関する講演を 振り返ってみると…
モバイル関連の機能・最新情報紹介 最新モバイルゲームの実例からみるUE4のモバイル向け機能・Tipsを 全部まるっとご紹介! + UE4.18 モバイル最新情報の紹介 https://www.slideshare.net/EpicGamesJapan/cedeckyushu-2017-ue4tips UE4のモバイル向け機能や最新情報などを改めて紹介!2019 https://www.slideshare.net/EpicGamesJapan/ue4mobilestudy
コンテンツアップデートについて UE4のモバイル開発におけるコンテンツアップデートの話 - Chunk IDとの激闘編 – https://www.slideshare.net/EpicGamesJapan/ue4-chunk-id 徹底解説!UE4を使ったモバイルゲーム開発における コンテンツアップデートの極意! https://www.slideshare.net/EpicGamesJapan/ue4-95204920
某ブログにて 【UE4 & Android】実機デバッグ実行中のログ確認方法について http://pafuhana1213.hatenablog.com/entry/2019/02/20/013340 UE4 & iOS開発時の実機デバッグ・プロファイリング方法 まとめ 2018 http://pafuhana1213.hatenablog.com/entry/2018/12/13/031332
振り返ってみると… モバイル開発において避けることができない モバイル特有のヒッチ メモリ問題 についてガッツリ話したことがない! ユーザのストレス・継続率に 大きく影響する重要な問題
これらの問題に対する対策が 不十分な場合、様々な問題が発生します
たとえば… ● プレイ中のカクツキ ● 長時間ロード ● 発熱からのパフォーマンス低下 ● 猛烈に減る電池 ● 突然のクラッシュ ● などなどなど…
やばい
早い段階から対策を入れることで ゲームをより快適にしていきましょう! (普段の開発も快適に!)
本日のお品書き ヒッチ対策 編 ● ● ● そもそもヒッチってなに? 一般的なヒッチ対策について モバイル特有のヒッチ対策について メモリ管理 編 ● ● なぜモバイル開発において問題になるのか メモリに関するプロファイル方法について 最新情報 編 ● UE4.23 で入った モバイル関連の便利機能・最適化について
そもそもヒッチってなに?
ヒッチ( Hitch )とは? ● 引っかける ● (くいなどに)つなぐ ● (…を)ぐいと動かす ● (ヒッチハイクで)させてもらう ● ヒッチハイクで行く Weblio英和辞書 より
いわゆる、カクつき
ゲームにおけるカクつき それまで滑らかに動いていたのが 急にカクついたり、一定時間画面が止まったり… https://youtu.be/6oR9GWGgBZY
イライラがすごい
海外だとHitchと表現することが多いため 本講演もそれに倣います Google先生に聞くときもこれを意識するのオススメ!
ヒッチは なぜ / いつ 起きる? あるフレーム(タイミング)で 非常に負荷が重い処理 、 または 大量の処理 が実行されたときに発生
ヒッチは なぜ / いつ 起きる? あるフレーム(タイミング)で 非常に負荷が重い処理 、 または 大量の処理 が実行されたときに発生
ヒッチを回避するには どうすればいいのか?
ヒッチ対策の基本的な方針 その1 負荷 を 削減
ヒッチ対策の基本的な方針 その2 処理の数 を 削減
ヒッチ対策の基本的な方針 その3 大量の処理 を 複数フレーム に 分散
ヒッチ対策の基本的な方針 その3.5 大量の処理 を 複数フレーム に 分散
ヒッチ対策の基本的な方針 その4 重い処理 を 複数フレーム に 分散
ここまでのまとめ ヒッチを回避するには どうすればいいのか? 負荷を 削減 ・分散する
本日のお品書き ヒッチ対策 編 ● ● ● そもそもヒッチってなに? 一般的なヒッチ対策について モバイル特有のヒッチ対策について メモリ管理 編 ● ● なぜモバイル開発において問題になるのか メモリに関するプロファイル方法について 最新情報 編 ● UE4.23 で入った モバイル関連の便利機能・最適化について
ヒッチが起きやすいタイミング ● アセット・レベルのロード ● オブジェクトの生成 ● ガベージコレクション(GC)
アセットのロード数を 削減 アセット間の参照関係を整理 ● 直接参照の場合 連鎖的にロード処理が走るため Unreal Fest East 2018 Nintendo Switch『OCTOPATH TRAVELER』は こうして作られた https://www.slideshare.net/EpicGamesJapan/ nintendo-switchoctopath-traveler
アセットのロード数を 削減・分散 レベルを複数のサブレベルに分割 ● ● 必要に応じてロード・アンロード ロードタイミングの分散
アセットのロード数を 分散 実際に使われる前に事前ロード(前読み) Qiita:Asset Managerのアセットの非同期ロード機能について
ヒッチが起きやすいタイミング ● アセット・レベルのロード ● オブジェクトの生成 ● ガベージコレクション(GC)
動的にActorを生成すると… アセットのロード後に各初期化処理が走る ● Construction Script, Begin Playなど BP_Bullet
オブジェクトの生成処理を 削減・分散 ● Construction Script, Begin Play における処理の削減・分散 ● 生成タイミング自体を分散 ● オブジェクトプール(常駐・使い回し)で分散
ヒッチが起きやすいタイミング ● アセット・レベルのロード ● オブジェクトの生成 ● ガベージコレクション(GC)
GCの対策 この資料読んで!以上! [4.20版] UE4におけるLoadingと GCのProfilingと最適化手法 https://www.slideshare.net/ EpicGamesJapan/ 420-ue4loadinggcprofiling-108367408
ここまでのまとめ これらの問題・対策は 全てのプラットフォームにおいて有効! 他にもヒッチの原因・対策はありますが… 負荷の削減・分散という考え方を大事にしましょう! もちろん プロファイリング をした上で!
本日のお品書き ヒッチ対策 編 ● ● ● そもそもヒッチってなに? 一般的なヒッチ対策について モバイル特有のヒッチ対策について メモリ管理 編 ● ● なぜモバイル開発において問題になるのか メモリに関するプロファイル方法について 最新情報 編 ● UE4.23 で入った モバイル関連の便利機能・最適化について
モバイル特有のヒッチ対策…?
なぜモバイル特有の問題が起きるのか? ハードウェア構成 と グラフィックAPI が 他のプラットフォームと異なるから!
モバイル端末のハードウェア構成 SoC (System on a Chip) を採用 ● ● CPU, GPU, メモリなどの各パーツをひとまとめにしたもの モバイル向けに省電力対応が入っている
モバイル端末のグラフィックAPI Windowsなどで採用されている DirectX ではなく モバイル向けのAPI ( OpenGL ES, Vulkan, Metal ) を採用
この違いにより何が起きるか… それは… Shader Compile 問題 メモリ転送速度 問題
Action RPGサンプルで検証 検証端末:Xperia Z5 ● ● Snapdragon 810 2015年10月発売
https://youtu.be/ArHDo9v4rJg
CPUプロファイラ計測結果 150 ms 100 ms 50 ms
CPUプロファイラ計測結果 150 ms 100 ms 50 ms Shader Compile 問題 メモリ転送速度 問題 が原因
強烈なヒッチが発生するため このモバイル特有の問題への 対応は必須です
そして、 本日ご紹介する対応を入れると…
https://youtu.be/n_bIFnrlxu0
ヒッチが完全に無くなります! これはもうやるしかないですよね…!?
やってやりましょう
モバイル特有のヒッチ対策について ● Shader Compile 問題 ● メモリ転送速度 問題
Shader Compile問題について ● なぜShader Compile問題が発生するのか? ● PSO キャッシュについて ● ● ● Tips ● ● ● 概要・流れ 使うために必要な操作・設定 PSOキャッシュによるPreCompile時間について ProgramBinaryCache ProgramLRUCache
本講演では「Shaderを使えるようにする処理」のことを Shader Compile とします 通常は Shader Compile は作業中だけですが… モバイルの場合 実機でも Shader Compile が行われます!
ActionRPG における 敵キャラ の 初出現時 の負荷を計測 検証端末:Xperia Z5 ( Snapdragon 810, 2015年10月発売 )
Action RPG における 敵キャラ初出現時の負荷 検証端末:Xperia Z5 ( 2015年10月発売 )
Action RPG における 敵キャラ出現時の負荷 Shader link Time : 471.014 ms Shader Compile処理の一部 約15フレーム(30fpsの場合) 検証端末:Xperia Z5 ( 2015年10月発売 )
なぜモバイルの場合 Shader Compileの問題が発生するのか?
実機上でShader Compileが問題になる理由 グラフィックスAPIの仕様 & モバイル端末のCPU性能
Android, iOSで採用されているグラフィックスAPI Android ● ● OpenGL ES Vulkan iOS ● ● OpenGL ES Metal
OpenGL ES 開発会社・端末(ドライバ)毎に 実装・対応している機能が異なる状況 オフライン(事前)Shader Compileができず 実機上で行う必要がある
OpenGL ES Shaderのソースコードを載せて、 実機上でShaderのCompile処理を実行 ソースコード Shader Program 中間データ Compile OpenGLShader() LinkProgram()
OpenGL ES Shader Compile処理が完了すると 描画に必要な Shader Program がメモリ上に確保される ● 2回目以降は↑を使い回す = 起動後に初めて使われる時のみShader Compileが走る ソースコード Shader Program 中間データ Compile OpenGLShader() LinkProgram()
Android, iOSで採用されているグラフィックスAPI Android ● ● OpenGL ES Vulkan iOS ● ● OpenGL ES Metal
時間などの関係で Vulkanの話は しません!!!
時間などの関係で Vulkanの話は しません!!! 少しします
Vulkanについて ローレベルなグラフィックスAPI OpenGL ESに比べてパフォーマンスが良い Vulkanが抱えている課題 古い端末の場合、 ドライバが原因でパフォーマンスが出ない
UE4とVulkanについて UE4.21リリースノートより ● OpenGL ES 3.1 との 機能互換性 が 100% ● OpenGL ES よりも 最大 20% 高速で実行できる可能性 GPU負荷に関しては少し上がる可能性あり (鋭意対応中)
Vulkanの採用を検討する基準についての参考情報 Vulkanによるパフォーマンス向上を見込める端末 ● Snapdragon 845 以上 ● Mali-G76 以上 FortniteにてVulkanを有効にしている端末 ( 2019年3月時点 ) ● Galaxy S9 ( Adreno ) ● Galaxy Note 9 ( Adreno, Mali ) ● Galaxy S10 ( Adreno, Mali )
UE4のVulkan対応に関する詳細資料 ● Vulkan! Powering AAA Experiences on Android https://www.unrealengine.com/ja/events/unreal-fest-europe-2019/vulkan-powering-aaaexperiences-on-android?lang=ja
Android, iOSで採用されているグラフィックスAPI Android ● ● OpenGL ES Vulkan iOS ● ● OpenGL ES Metal 非推奨になったため UE4.24で サポート対象外に
Metal ローレベルなグラフィックスAPI OpenGL ESに比べてパフォーマンスが良い
Metal オフラインShader Compileが可能 実機上でShader Compileしなくていい Working with Metal: Overview https://developer.apple.com/videos/play/ wwdc2014/603/
オフラインShader Compileをするには ● Mac上でビルドする ● Enable Remote Shader Compileを 有効にした状態でリモートビルド (UE4.21, 4.22で不具合あり。4.23で修正)
Metalに関する負荷 Shaderの初回使用時に Pipeline State Object の生成処理が必要 ● ● GPUに渡す描画設定リスト OpenGL ESと同様に 2回目以降は生成されたものを使い回す この生成処理がモバイルのCPU性能では 非常に重く…ヒッチの原因に… https://software.intel.com/en-us/blogs/2014/07/23/direct3d12-overview-part-2-pipeline-state-object
Action RPG における 敵キャラ初出現時の負荷 検証端末:iPhone 7 ( 2016年9月発売 )
Action RPG における 敵キャラ初出現時の負荷 PipelineState time : 189.698 ms 検証端末:iPhone 7 ( 2016年9月発売 )
ざっくりまとめ 起動後 に 初めて 使われる Shaderの場合 Shader Compile 処理で生成されるデータが必要 ● Shader Compile処理は非常に重い 生成されたデータは使い回せるため、 1度使用されたShaderを再度使うときは Shader Compile処理が走らない OpenGL ESの場合は 生成されたデータはアプリ終了時に消去されるため 2回目以降の起動でも、初回使用時はShader Compileが必要になる
Shader Compileの負荷問題に どう対策するか?
グラフィックスAPIの標準機能を活用する方法 Shader Compile結果をストレージに保存することで 2回目以降の起動でも再利用可能に ● ● Android : iOS : GL_OES_get_program_binary 拡張 Metalの標準機能 問題 ● ● 初回起動 かつ 初回使用時のヒッチが解決できない Androidの場合、メモリ使用量が膨大になる
この問題を解決するために生まれた機能が… Pipeline State Object (PSO) キャッシュ ( FShaderPipelineCache )
Shader Compile問題について ● なぜShader Compile問題が発生するのか? ● PSO キャッシュについて ● ● ● Tips ● ● ● 概要・流れ 使うために必要な操作・設定 PSOキャッシュによるPreCompile時間について ProgramBinaryCache ProgramLRUCache
PSOキャッシュはどういう機能? 事前に作成したShaderのリストを元に Shader の PreCompile ( WarmUp ) を行う機能
PSOキャッシュが ない とき ヒッチ 発生! Shader Compile ! メモリ キャッシュ
PSOキャッシュが ある とき PreCompile ! キャッシュ
PSOキャッシュ使用前 ● CreateBoundShaderState time ● Shader link Time : 472 ms : 471 ms PSOキャッシュ使用後 ● CreateBoundShaderState time ● Shader link Time : 0.6 ms :0 ms 470ms あった負荷が 1ms以下に!
PSOキャッシュの流れ ~ 事前準備からPreCompileまで ~
まずはイメージを掴むため 簡略した流れを紹介
PreCompileを行うための事前準備 を圧縮した 実機上でゲームをプレイし Shaderの組み合わせリスト を作成 を含めた ユーザへの配布パッケージを作成
ユーザがプレイする際の実機上での処理 のリストにあるShaderに対して Shader Compile。結果はメモリに保存 メモリに保存された結果を再利用 (Shader Compileをスキップ)
開発 環境 本番 環境
各処理の詳細について説明しますが 今は細かい部分は無視してダイジョブです ふいんき(←なぜか変換できない) を感じてください
1. Shaderの組み合わせリストの収集 後述の設定を行った後にCookして Stable Shader情報リスト( *.scl.csv )を生成 ● /Saved/Cooked/<PLATFORM>/<PROJECT>/Metadata/PipelineCaches
scl.csvの中身
scl.csvの中身 Key Value ClassNameAndObjectPath Material /Engine/EngineMaterials/DefaultTextMaterialOpaque.DefaultTextMaterialOpaq ue ShaderType TMobileBasePassPSFMobileMovableDirectionalLightAndSHIndirectPolicyIN T32_MAXHDRLinear64Skylight ShaderClass MeshMaterial MaterialDomain MD_Surface FeatureLevel ES3_1 QualityLevel High TargetFrequency SF_Pixel TargetPlatform GLSL_ES3_1_ANDROID VFType FLocalVertexFactory Permutation Perm_0 OutputHash 8970309F7B3BF9D92B463D067104580E5AAA3519
2. PSOデータの収集 実機上でゲーム、又はテストレベルを動作させることで Binary PSO ( *.rec.upipelinecache ) を生成 ● /storage/emulated/0/UE4Game/<PROJECT>/Saved/CollectedPSOs Stable Shader Binary PSO
注意 Android上で生成したBinary PSOを iOS向けビルドで使用することはできません ● Android, iOSでShaderのソースコードが異なるため Binary PSO for Android Binary PSO for iOS
3. PSOキャッシュのビルド Binary PSO ( *.rec.upipelinecache ) と Stable Shader ( scl.csv ) から Pipeline Metadata ( *.stablepc.csv )をビルド Stable Shader Pipeline Metadata Binary PSO
stablepc.csv の中身 なるほどわからん
4. パッケージング・実行 /Build/<PLATFORM>/PipelineCache に Pipeline Metadata ( *.stablepc.csv ) を入れた後に Packaging or Launch ● <PLATFORM> = Android or iOS ● Cook 時に Binary PSO ( *.stable.upipelinecache ) に変換 Pipeline Metadata バイナリ形式に圧縮 Binary PSO 不要な情報を削除
5. PreCompile アプリの起動直後、Binary PSO ( *.stable.upipelinecache ) を元に Shader Compile処理を実行 ● FShaderPipelineCache::Precompile() Create~Shader Shader Program SetGraphicsPipelineState
超ざっくりまとめ 1. 実機上でゲームをプレイして シェーダの組み合わせリストを収集 2. そのリストを用いて、起動直後にShader Compile 結果をメモリにキャッシュとして保存 3. Shaderを実際に使うとき そのキャッシュを再利用することでヒッチを回避 開発 環境 本番 環境
PSOキャッシュを使う上で 必要となる作業・設定について
PSOキャッシュの使い方 公式ドキュメント 概要 https://docs.unrealengine.com/en-US/Engine/Rendering/PSOCaching/index.html リファレンス https://docs.unrealengine.com/ja/Engine/Rendering/PSOCaching/PSOReference/index.html FAQ https://docs.unrealengine.com/ja/Engine/Rendering/PSOCaching/FAQ/index.html 1. 2. 3. 4. 5. PSO キャッシングの有効化とビルド https://docs.unrealengine.com/ja/Engine/Rendering/PSOCaching/EnablingBuildingPSOCaching/index.html PSO データの収集 https://docs.unrealengine.com/ja/Engine/Rendering/PSOCaching/GatheringPSOData/index.html PSO キャッシュのビルド https://docs.unrealengine.com/ja/Engine/Rendering/PSOCaching/BuildingPSOCache/index.html PSO キャッシングを使用した UE4 プロジェクトのビルド https://docs.unrealengine.com/ja/Engine/Rendering/PSOCaching/BuildingUE4ProjectWithPSOCaching/index.html PSO キャッシング データのコンパイルと使用 https://docs.unrealengine.com/ja/Engine/Rendering/PSOCaching/CompilingUsingPSOCachingData/index.html
PSOキャッシュの使い方 ざっくり説明 1. r.ShaderPipelineCache.Enabled、 Share Material Shader Code, Shared Native Shader Librariesが有効の状態で コマンドラインパラメータに -logPSO を追加したパッケージを作成し、 一通りゲームを遊ぶ(又は、PSOキャッシュ収集用レベルを開く) 2. 1の過程で生成された *.scl.csv と *.rec.upipelinecache から *.stablepc.csv を生成 3. *.stablepc.csv を含むパッケージを作成 4. アプリ起動後にShaderをPreCompile PreCompile完了後、PSOキャッシュデータの対象となるShaderは そのデータを再利用するため、Shader Compileが不要に
検証を楽にするために batファイルを作りました よく使う ADBコマンド を呼び出すエディタ拡張もあります https://github.com/pafuhana1213/AdbCommandWidgetSample/tree/master/Plugi ns/AdbCommandEditorWidget/Bat iOS向けは…いつか…
UE4.23 から Stable Shader情報リスト( *.scl.csv ) を 出力するには AndroidEngine.ini / iOSEngine.ini に 以下を追記する必要があります ● リストの構築・生成時間、ファイルサイズを改善するため [DevOptions.Shaders] NeedsShaderStableKeys = true
すこーし手間はかかりますが Shader Compileによるヒッチ は PSOキャッシュで回避可能! PSOキャッシュ最高!大好き!!結婚しよう!!! …と終わればいいのですが、うまい話だけではなく 注意すべきことが幾つかあります
Shader Compile問題について ● なぜShader Compile問題が発生するのか? ● PSO キャッシュについて ● ● 概要・流れ 使うために必要な操作・設定 ● Tips ● ● ● PSOキャッシュによるPreCompile時間について ProgramBinaryCache ProgramLRUCache
PSOキャッシュによる PreCompile時間について
PreCompileのタイミングについて デフォルト設定の場合、 アプリ起動時( Engine の PreInit ) に PreCompile を開始
PreCompile時間の問題 PSOキャッシュによる PreCompile は 大量のShader Compile を 実行することになる PreCompile対象のShaderが増えると、 ゲームを遊べるまでの待ち時間も増える PreCompile中
PreCompile時間の問題 Action RPGの場合:4.65 ● 秒 (Xperia Z5 ) LogRHI: Warning: FShaderPipelineCache completed 64 tasks in 4.41s (4.65s wall time since intial open). 一定規模以上のプロジェクトの場合 数分レベルの待ち時間が発生することも…
PreCompile 時間の問題への対策 ● PreCompile処理を分散する ● PreCompile対象のShaderを制限する ● PreCompile対象のShaderを削減する
PreCompile 処理を分散する方法 起動直後にPreCompileを実行しないように ● r.ShaderPipelineCache.StartupMode 0 PreCompile処理の開始 ● r.ShaderPipelineCache.SetBatchMode 1 or 2 PreCompile処理の中断 ● r.ShaderPipelineCache.SetBatchMode 0
r.ShaderPipelineCache.SetBatchMode について PreCompileの処理優先度を設定可能 Fast Mode (デフォルト) ● ● r.ShaderPipelineCache.SetBatchMode 2 暗転中やローディング画面中に、全力でPreCompile Background Mode ● ● r.ShaderPipelineCache.SetBatchMode 1 ゲームプレイ中の裏で、少しずつPreCompile
おまけ r.ShaderPipelineCache.SetBatchMode は何を制御してるか 1フレームにおける PreCompileするShader数 と PreCompile処理に費やす時間 PreCompileするShader数 ● ● r.ShaderPipelineCache.BatchSize r.ShaderPipelineCache.BackgroundBatchSize PreCompile処理に費やす時間 ● ● r.ShaderPipelineCache.BatchTime r.ShaderPipelineCache.BackgroundBatchTime
PreCompileのタイミングをズラした際の注意点 PreCompileが未完了なShaderが使用されると PSOキャッシュの恩恵を受けることができません! PSOキャッシュを100%活かす為には 全PreCompileの完了を待つ処理が必要!
Pause Background
Background Fast PreCompile 完了
PreCompileの終了タイミング FShaderPipelineCache :: GetPrecompilationCompleteDelegate() または FShaderPipelineCache :: NumPrecompilesRemaining()
PreCompile時間の問題への対策 ● PreCompileのタイミングをズラす ● PreCompile対象のShaderを制限する ● PreCompile対象のShaderを削減する
PreCompileのタイミングをズラす方法の問題点 タイミングをずらす・分散しただけなので、 ワーストケースでは数分レベルの待ち時間が発生 PreCompileするShader数が多いと パッケージサイズ、メモリ使用量にも悪影響が…
PSOキャッシュ機能を使う上で大事なこと (ほぼ)全てのShaderを PSOキャッシュの対象にしようとしない
(ほぼ)全てのShaderを対象としない理由 先述の問題 ● PreCompile処理時間、メモリ、パッケージサイズ PSOキャッシュの事前準備コスト ● ゲームを最初から最後まで 様々な行動をしながらプレイする必要がある ● しかも、 2つのOSで苦労も2倍
どんなShaderを PSOキャッシュの対象にすればいいのか?
Shader Compileが必要なタイミング Shaderが初めて使われるとき オブジェクトを動的に生成したとき ヒッチが起きると遊びの邪魔になりストレスに レベルをロードしたとき 暗転・ローディング画面を表示中なことが多いため ヒッチが起きても影響が少ない PSOキャッシュで 優先的に対応すべきなのは こちら!
PSOキャッシュ対象のShaderを絞るためには… 対象のShaderを使用するオブジェクトのみを配置した PSOキャッシュ収集用レベルを構築・使用!
PSOキャッシュ収集用レベルの例 Qiita : UE4 Shader Pipeline Cache に 乗っていないShaderーを調査する (@Takezoh さん ) イカロスM ポストモーテム講演
EditorScripting で PSOキャッシュ収集用レベルを自動生成
PreCompile時間の問題への対策 ● PreCompileのタイミングをズラす ● PreCompile対象のShaderを制限する ● PreCompile対象のShaderを削減する
マテリアルの管理に注意しないと Shaderの数は簡単に膨れ上がります 数を抑えることで PreCompileの対象を減らせます
Shaderの組み合わせリスト
Shaderの組み合わせリスト Shaderの組み合わせを減らすと、Shaderの数は減る
Shaderの組み合わせリスト Shaderの組み合わせを減らすと、Shaderの数は減る (逆もまた然り)
この部分を減らすためには…
Shaderの数を減らす / 増やさないためには… その1 Material の Usage にて 不要な項目は必ず無効に ● Usage毎に別Shaderが生成されるため
この部分を減らすためには…
Shaderの数を減らす / 増やさないためには… その2 ( Mobile ) Shader Permutation Reduction を活用 ● プロジェクトで使用しない機能をOFFにすることで 不要なShaderの生成を防ぐ機能
詳細はこちら https://www.slideshare.net/EpicGamesJapan/epic-games-japan-ue4dd
Shaderの数を減らす / 増やさないためには… その3 不要な設定・アセットが パッケージに含まれないようにする モバイル以外の プラットフォームも対応する際に重要
詳細はこちら https://www.slideshare.net/EpicGamesJapan/ue4mobilestudy
PreCompile時間の問題への対策 ● ● ● PreCompileのタイミングをズラす ● 起動直後ではなく、ゲームフローに適したタイミングに ● 動的に生成するものなど、ヒッチが目立つものを優先的に ● 不要な設定を切ることで、Shaderの組み合わせを減らす PreCompile対象のShaderを制限する PreCompile対象のShaderを削減する
Shader Compile問題について ● なぜShader Compile問題が発生するのか? ● PSO キャッシュについて ● ● 概要・流れ 使うために必要な操作・設定 ● Tips ● ● ● PSOキャッシュによるPreCompile時間について ProgramBinaryCache ProgramLRUCache
ProgramBinaryCache ( Android OpenGL ES専用 )
OpenGL ES の PreCompileの問題点 OpenGL ES には Shader Compile結果を 次回起動以降に再利用する機能が標準では用意されていません 起動の度に、ソースコードからの Shader Compile という高負荷な処理が必要に
ProgramBinaryCacheとは? PSOキャッシュによるPreCompile結果を保存し 次回起動時に再利用することでPreCompileを短縮する機能 r.ProgramBinaryCache.Enable (デフォルト:有効)
PreCompile時間短縮効果 ProgramBinaryCache:無効 ProgramBinaryCache:有効 ● 1回目:4.41 s ● 1回目:4.36 s ● 2回目:2.03 s ● 2回目:0.54 s ActionRPG ( XperiaZ5 )で計測 とあるプロジェクトにおける事例 2分 → 10秒
ProgramBinaryCache 初回起動時 PreCompileの過程で生成された Program Binary (glProgramBinary) を ストレージに保存 ● /storage/emulated/0/Android/data/ <PACKAGE_NAME>/files/ProgramBinaryCache Shader ソースコード Shader Program PreCompile Program Binary 抽出
ProgramBinaryCache 2回目以降 PreCompile時に ストレージ内のProgram Binary から Shader Program を 生成 ● ● ソースコードからの変換に比べて格段に高速 FOpenGLProgramBinaryCache::ScanProgramCacheFile
PreCompile 開始 Program Binary は ある? はい Program Binary から Shader Program を 生成 いいえ ソースコード から Compile Shader Program 生成 Program Binary 保存
補足 ● 注意:PSOキャッシュ使用前提の機能です ● r.OpenGL.StoreCompressedProgramBinaries で更に圧縮可能 ただし解凍コストが発生 ● UE4.20以前は PSOキャッシュ関係なく バイナリを保存する機能でしたが、メモリ使用量などの問題で仕様変更 ( r.UseProgramBinaryCache )
ProgramBinaryCacheには PSOキャッシュによる初回PreCompile後に アプリを再起動する機能があります
初回PreCompile後にアプリを再起動する機能 r.ProgramBinaryCache.RestartAndroidAfterPrecompile (デフォルト:有効) https://youtu.be/OAkKAqz709k
なんで再起動するん? ソースコードからのCompile過程で発生した 余分なメモリ消費をリセットするため PreCompile 開始 Program Binary は ある? はい Program Binary から Shader Program を 生成 いいえ ソースコード から Compile Shader Program 生成 Program Binary 保存
注意 デフォルトの場合、ユーザから見ると突然再起動が走ることに 再起動することを通知する画面があると安心 ● 再起動処理を行っている FOpenGLProgramBinaryCache:: OnShaderPipelineCachePrecompilationComplete()を拡張 プラットフォームによっては 再起動することにNG出る可能性も。事前に要確認 メモリに余裕のあるプロジェクトの場合は 無理に再起動しなくても問題なし
Shader Compile問題について ● なぜShader Compile問題が発生するのか? ● PSO キャッシュについて ● ● 概要・流れ 使うために必要な操作・設定 ● Tips ● ● ● PSOキャッシュによるPreCompile時間について ProgramBinaryCache ProgramLRUCache
ProgramLRUCache ( Android OpenGL ES専用 )
とあるプロジェクトで発生した問題 Adreno 端末: ● Program Binary 40MB から生成される Shader Program が 400MB以上 に Mali 端末: ● Shader Program の メモリ使用量が一定値を超えると描画が破綻 破綻のイメージ図
ProgramLRUCache メモリ使用量、又はShader Program数が一定値を超えた際に 使用頻度が低い Shader Program をメモリから破棄する機能 ● LRU = Least Recently Used r.OpenGL.EnableProgramLRUCache (デフォルト:無効) https://stackoverflow.com/questions/13337854/ understanding-lru-algorithm
破棄を開始する基準について r.OpenGL.ProgramLRUBinarySize ● ● メモリ上に格納する Shader Program の 最大バイト数 デフォルト値:35*1024*1024 r.OpenGL.ProgramLRUCount ● ● メモリ上に格納する Shader Program の最大数 デフォルト値:700 デフォルト値は経験的に設定された値ですが 実際は端末によって最適値が異なります
メモリ
メモリ
Shader Compile ! Shader Program メモリ
Shader Programによる メモリ使用量が増大 Shader Program Shader Compile ! Shader Compile ! Shader Program Shader Program
使用頻度の低い Shader Program から 再生成用のProgram Binaryを作成 Shader Program Program Binary Shader Program Shader Program
使用頻度の低い Shader Programを メモリから破棄 Program Binary Shader Program Shader Program Shader Program
Shader Programによる メモリ使用量が減少! Program Binary Shader Program Shader Program
破棄したShader Programが 再度必要になると… Program Binary Shader Program Shader Program
Program Binaryから再生成するので Shader Compileは走らない Shader Program Program Binary Shader Program Shader Program
再生成後、 Program Binaryをメモリから破棄 Shader Program Shader Program Program Binary Shader Program
ProgramLRUCache のオプション r.OpenGL.ProgramLRUKeepBinaryResident ● ● 再生成用のProgram Binary を メモリ上に保持し続けるか否かの制御 デフォルト:無効
ProgramLRUKeepBinaryResident が 有効の場合
r.OpenGL.ProgramLRUKeepBinaryResident:有効の場合 使用頻度の低いShader Program を メモリから破棄するところまでは無効時と同じ Program Binary Shader Program Shader Program
r.OpenGL.ProgramLRUKeepBinaryResident:有効の場合 Shader Programを再生成した後も メモリ上に Program Binaryを保持し続けることが異なる点 Program Binary Shader Program Shader Program Shader Program
r.OpenGL.ProgramLRUKeepBinaryResident:有効の場合 Shader Programを再生成した後も メモリ上に Program Binaryを保持し続けることが異なる点 Program Binary Shader Program Shader Program Shader Program
パフォーマンス メモリ使用量 : : 無効 < 有効 無効 > 有効
ここまでのまとめ ProgramBinaryCache ● Shader Compile結果をストレージに保存することで 2回目以降の起動時のPreCompile時間を短縮する機能 ProgramLRUCache ● Shader Compileによって生成された Shader Programのメモリ使用量を制限する機能 これらの機能を使っても問題が解決しない場合は 「PreCompile時間の問題への対策」を再度検討しましょう!
Shader Compile編のまとめ ● モバイルの場合、実機上でShader Compileが走るため 対策を入れていない場合は強烈なヒッチが発生 ● PSOキャッシュを使って PreCompile することで ユーザにストレスを与えるヒッチを回避可能 ● PreCompileのタイミング、Materialの管理、 メモリ使用量の調整など注意すべき点がいくつか存在 ゲームフローにも影響するため、 開発初期段階から検証・導入していきましょう!
おまけ rhi.Metal.CacheShaderPipelines ● Pipeline State Object(PSO)をメモリ上に保持し続けるか否か ● 有効(デフォルト):保持し続ける ● 無効: すべてのRHI参照が解放されると、PSOをメモリ上から削除 メモリ節約になるが、再利用時にPSOを再生成するコストが発生 https://docs.unrealengine.com/ja/Support/Builds/ReleaseNotes/4_22/index.html
Part 2へ