unityでいってみよう!

unityがチョットワカル位の人のブログ

【2020年度】Grapchics Jobs 完全理解

はじめに

皆さん、Graphics Jobs 使っていますか? この機能、簡単に説明すると 描画処理にJob Systemを使用してアプリケーションのパフォーマンスを向上させる機能 です。 この機能の歴史は古く、Unity5.6の頃には既にあったと思いますが、いまだにExperimentalが付いたままである事からの非常に難産である事が判ります。(スタンドアローンなど、一部のプラットフォームではExperimentalが外れているようではあります)Unity2018.4.23f1 Relese Note 解説にも記載しましたが、実は、Unity2018、2019、2020において何時の頃か判りませんが、ProjectSettingsで有効にしていた場合でも機能が無効となっていました。

unityletsgo.hatenablog.com

そこで今回はGraphics Jobsについて改めて検証をおこないました。

だらだら書いているので、組み合わせ一覧とまとめを見るだけでもOKですが、順に読むことで理解が深まります。

Grapchics Jobsが機能するUnityのバージョンについて

リリースノートに記載されている下記が該当するissueです。

Graphics: Fixes an issue where graphics settings were written to boot.config incorrectly. (1236936)

このissueは下記のバージョンで修正されています。

  • 2018.4.23f1
  • 2019.3.14f1
  • 2020.1.0b8
  • 2020.2.0a9

Graphics Jobsの機能を試してみる場合は必ずこのバージョン以降をご使用下さい。

boot.config

issueの内容としては、「boot.configに記述されたGraphics Settingsの内容が間違っていた。」とありますが、boot.configとはどこにあり、どう間違っていたのかを確認します。

boot.configの在りか

boot.configがプロジェクトをビルドする際に作成されます。 いきなりバイナリを作成するのではなく、一度各プラットフォーム用のプロジェクト形式へエクスポートすると確認しやすいと思います。

{GradleProject}/unityLibrary/src/main/assets/bin/Data/boot.config
{XcodeProject}/Data/boot.config

boot.configの中身

PlayerSettingsからGraphics jobsにチェックを入れた状態でプロジェクトをビルドすると、2019.3.13と2019.3.14では下記の部分に差分があります。

2019.3.13f1

gfx-enable-gfx-jobs=
gfx-enable-native-gfx-jobs=

2019.3.14f1

gfx-enable-gfx-jobs=1
gfx-enable-native-gfx-jobs=1

どうやら、1を書き忘れていた為、機能が有効になっていなかったようです。 正直、Unityをバージョンアップしなくてもboot.configの記述さえ修正すればGrapchics Jobsは機能しているように見えますが、それは誰も保証できませんので自己責任でお願いします。

なお、Multithread Renderingにチェックを入れなかった場合、 2019.3.13f1

gfx-disable-mt-rendering = 

2019.3.14f1

gfx-disable-mt-rendering = 1

と同様の修正が行われているのですが、こちらに関しては2019.3.13f1でも機能の切り替えは正常に動作していることを確認しました。この辺りの動作の違いは謎です。 また、変数名にdisable命名するのも落ち着かないので止めて頂きたいです。

gfx-jobsGraphics Jobsの略称であるのは何となく想像がつくのですが、gfx-enable-gfx-jobsと gfx-enable-native-gfx-jobsの2種類が存在します。nativeとは一体なんのことでしょうか・・・・。

GraphicsJobMode

調査して判明したのですが実はこれは、GraphicsJobModeを指しています。 PlayerSettingsにはgraphicsJobModeという変数が存在するのですが、こちらにGraphicsJobMode.NativeまたはGraphicsJobMode.Legacyを設定します。

docs.unity3d.com Unity - Scripting API: GraphicsJobMode

GraphicsJobMode.Nativeを指定するとboot.configにはgfx-disable-mt-rendering = 1が記述され、GraphicsJobMode.Legacyを指定すると記述が消えます。

このことから、Grapchics Jobsは有効・無効の2種類ではなく、 - Native - Legacy - 無効 の3種類であるということが判りました。

なお、PlayerSettings.graphicsJobModeにはGUIは存在しませんのでScriptから設定する必要があります。

RenderingThreadingMode

PlayerSettings.graphicsJobModeに関しては、Google先生に聞いてもほぼ情報が無い状態ですが、UnityのScripting APIでSystemInfo.renderingThreadingModeという変数の説明で下記のように記述されていました。

pplication's actual rendering threading mode (Read Only).

Rendering threading mode is decided during the Unity application startup, according to the combination of Player Settings PlayerSettings.MTRendering, PlayerSettings.graphicsJobs and PlayerSettings.graphicsJobsMode, as well as according to the target platform capabilities.

docs.unity3d.com

ようは、 Mulithread RenderingGraphics JobsGraphics Jobs Modeの3種類の変数の組み合わせで、Rendering Threading Modeの組み合わせが確定するようです。

Graphics Jobs登場時のUnity Blogでは下記のようにMultithreaded RenderingGraphics Jobsを同時に有効にするなと記載されていますが、時代は変わったようです。

注意 ― Android をターゲットにするとき、“Multithreaded Rendering” と “Graphics Jobs (Experimental)” 設定を絶対に同時には有効にしないように気を付けてください。その 2 つは互いに排他的なので、最終リリース版では、Graphics Jobs を有効にすると、警告なしに Multithreaded Rendering は無視されるようになります。

blogs.unity3d.com

RenderingThreadingModeには全6種類のモードが存在します。 以下各モードを解説します。

RenderingThreadingMode.Direct

f:id:kimukats:20200601162435p:plain

MainThreadから直接Graphic Commandを実行します。 シングルスレッドで実行される為、安定しています。コア数が1のデバイスはどのモードを指定してもこのモードにフォールバックされるようです。

RenderingThreadingMode. MultiThreaded

f:id:kimukats:20200601162851p:plain

MainThreadから中間コマンドを作成し、RenderThreadからも参照出来る共有バッファへ書き込みます。 RenderThreadは共有バッファの内容からGraphic Commandを実行します。

iPhone7以前のようなCore数が少ない(2コア程度)の端末に適している傾向にあります。

RenderingThreadingMode.LegacyJobified

f:id:kimukats:20200601163339p:plain

複数のWorkerThreadが中間コマンドを作成し、共通バッファに書き込みます。 RenderThreadが共通バッファの内容を元にGraphic Commandを実行します。 MultiThreadedでMainThreadが行っていた内容をWorkerThreadで行うように改良したモードです。

ユーザースクリプトの処理が長い等、コア数が多く、MainThereadを少しでもあけたい場合はこのモードが有効です。 (2コアであれば、MultiThreaderの方がパフォーマンスが高い傾向にあります。) Androidではサポートしておらず、このモードを選択した場合はNativeGraphicsJobsへフォールバックします。

RenderingThreadingMode. NativeGraphicsJobs

f:id:kimukats:20200601163717p:plain

MultiThreadedで行っていたRenderingThreadの処理をWorkerThereadへ分散したモードです。 RenderingThreadの処理が長い場合、WorkerThreadに処理を逃がすことが出来る為、コア数が多い端末ではパフォーマンスの改善を見込めます。

RenderingThreadingMode. NativeGraphicsJobsWithoutRenderThread

f:id:kimukats:20200601164055p:plain DirectでMainThreadが行っていたGraphicAPIの発行処理をWorkerThreadへ分散するモードです。 中間コマンドを作成せず、複数のスレッドで直接Graphics Commandを発行する為、処理の改善効果が期待出来ます。

組み合わせ一覧

各Rendering ThreadingMode に切り替える為のMultiThread Rendering、Graphics Jobs、Graphics Jobs Modeの組み合わせと対応するプラットフォームの表です。 〇の後ろに続く括弧の中身は必須のGrapchics APIです。 また、Development Buildを有効にしてビルドを行った場合、デバッカ等を使用して実行時に引数を指定することで強制的にモードを切り替えることが可能です。

Rendering ThreadingMode MT Rendering Graphics Jobs Graphics Jobs Mode 引数 Android iOS
Direct OFF OFF - -force-gfx-direct
SingleThreaded - _ - -force-gfx-st
MultiThreaded ON OFF - -force-gfx-mt
LegacyJobified ON ON Legacy -force-gfx-jobs legacy × 〇(Metal)
NativeGraphicsJobs ON ON Native -force-gfx-jobs native 〇(Valkan) 〇(Metal)
NativeGraphicsJobsWithoutRenderThread OFF ON - -gfx-enable-gfx-jobs -gfx-disable-mt-rendering 〇(Valkan) 〇(Metal)

※ SingleThreadedはMultiThreadedののデバックバージョンで、RenderThreadで行っていた処理をMainThreadで処理します。

まとめ

  • 機能しなくなっていたGraphics Jobsが動作するように修正されました。
  • Graphics Jobsの機能を有効にする為には特定のGraphicsAPI(Android:Vulkan,iOS:Metal)を使用することが必須であることは変わらず
  • Graphics JobsとMultithreadRenderingは排他利用ではなくRenderingThreadingModeという機能に統合された
  • RenderingThreadingModeのどのモードが良いかはデバイスのコア数やプロジェクトに依存する為、実際にプロジェクトをProfilingしながら決定する必要がある。