Version: 2020.1
言語: 日本語
CullingGroup API
グラフィックスパフォーマンスの最適化

テクスチャとメッシュデータのロード

Unity は、同期と非同期の 2 種類の方法で、テクスチャやメッシュのデータをディスクから読み込み GPU にアップロードします。この 2 つの処理は “同期アップロードパイプライン” と “非同期アップロードパイプライン” と呼ばれます。

Unity が同期型アップロードパイプラインを使用すると、データをロードしてアップロードしている間は、他のタスクを実行できません。これにより、アプリケーションに目に見える一時停止が発生することがあります。Unity が非同期アップロードパイプラインを使用すると、バックグラウンドでデータのロードとアップロードを行いながら、他のタスクを実行できます。

テクスチャやメッシュに対して非同期アップロードパイプラインを使用できる場合、Unity は自動的に非同期アップロードパイプラインを使用します。テクスチャやメッシュに非同期アップロードパイプラインを使用できない場合、Unity は自動的に同期アップロードパイプラインを使用します。

仕組み

同期アップロードパイプラインと非同期アップロードパイプラインの主な違いは、ビルド時に Unity がデータを保存する場所で、それがランタイムに Unity がデータを読み込む方法に影響します。

同期アップロードパイプラインでは、Unity は、1 つのフレームで、テクスチャやメッシュのメタデータ (ヘッダーデータ) と、テクセル/頂点データ (バイナリデータ) の両方を読み込む必要があります。非同期アップロードパイプラインでは、Unity は 1 つのフレームでヘッダーデータのみをロードする必要があり、その後のフレームでバイナリデータを GPU にストリーミングすることができます。

同期型アップロードパイプラインでは、以下が行われます。

  • ビルド時に、Unity はメッシュやテクスチャのヘッダーとバイナリデータの両方を 1 つの .res ファイルに書き込みます。
  • ランタイムに、アプリケーションがテクスチャやメッシュを必要とするとき、Unity はそのテクスチャやメッシュのヘッダーデータとバイナリデータの両方を .res ファイルからメモリにロードします。すべてのデータがメモリに入ると、Unity はバイナリデータをメモリから GPU にアップロードします。ロードとアップロードの作業は、主にメインスレッドで、1 フレーム内で行われます。

非同期のアップロードパイプラインでは、以下が行われます。

  • ビルド時に、Unity はヘッダーデータを .res ファイルに、バイナリデータを別の .res ファイルに書き込みます。
  • At runtime, hen the application needs the texture or mesh, Unity loads the header from the .res file into memory. When the header is in memory, Unity then streams the binary data from the .resS file to the GPU using a fixed-sized ring buffer. Unity streams the binary data using multiple threads, over the course of several frames. Note that on some console platforms where Unity already knows the GPU hardware, Unity skips the ring buffer and loads straight into the GPU memory.

テクスチャとメッシュデータの適格性

テクスチャは、以下の条件を満たすと、非同期アップロードパイプラインの対象となります。

  • テクスチャは読み取り/書き込み可能ではない。
  • テクスチャは Resources フォルダーに入っていない。
  • ビルドターゲットが Android の場合、プロジェクトのビルド設定で LZ4 圧縮が有効になっている。

なお、LoadImage(byte[] data) を使用してテクスチャをロードする場合、上記の条件が満たされていても、強制的に同期アップロードパイプラインが使用されます。

メッシュは、以下の条件を満たすと、非同期アップロードパイプラインの対象となります。

  • メッシュは読み取り/書き込み可能ではない。
  • メッシュは Resources フォルダーに入っていない。
  • メッシュは BlendShape ではない。
  • メッシュが動的バッチ処理に不適格であるか、動的バッチ処理が無効になっているため、Unity がメッシュに動的バッチ処理を適用していない。動的バッチ処理の詳細については、ドローコールバッチング を参照してください。
  • メッシュの頂点/インデックスデータが、パーティクルシステム、Terrain (地形)、メッシュコライダーで必要とされていない。
  • メッシュに ボーンウェイト がない。
  • メッシュ トポロジークワッド ではない。
  • メッシュアセットの meshCompressionOff に設定されている。 ビルドターゲットが Android の場合、プロジェクトのビルド設定で LZ4 圧縮が有効になっている。

それ以外の状況では、Unity はテクスチャとメッシュを同期してロードします。

Unity が使用するアップロードパイプラインを特定する方法

Profiler または他のプロファイリングツールを使用して、スレッドのアクティビティとプロファイラーのマーカーを観察することによって、Unity が非同期アップロードパイプラインを使用していることを特定できます。

以下は、Unity がテクスチャやメッシュのアップロードに非同期アップロードパイプラインを使用していることを示しています。

  • AsyncUploadManager.ScheduleAsyncReadAsyncReadManager.ReadFileAsync.DirectTextureLoadBegin プロファイラーマーカー。
  • AsyncRead スレッドでのアクティビティ。

このアクティビティが表示されない場合、Unity は非同期アップロードパイプラインを使用していません。

なお、以下のプロファイラーマーカーは、Unity が非同期アップロードパイプラインを使用していることを示すものではありません。これらは、非同期アップロード作業が必要かどうかをチェックするために呼び出されます。

  • Initialization.AsyncUploadTimeSlicedUpdate
  • AsyncUploadManager.AsyncResourceUpload
  • AsyncUploadManager.ScheduleAsyncCommands

非同期アップロードパイプラインの設定

非同期アップロードパイプラインの設定を行うことができます。なお、同期アップロードパイプラインの設定はできません。

Quality 設定の Async Upload 設定
Quality 設定の Async Upload 設定

非同期アップロードバッファ

Unity では、1 つのリングバッファを再利用して、テクスチャやメッシュデータを GPU にストリーミングします。これにより、必要なメモリ割り当ての数を減らすことができます。

Async Upload Buffer は、このリングバッファのサイズをメガバイト単位で決定します。最小サイズは 2 で、最大サイズは 512 です。

Unity は、現在ロードしている最大のテクスチャやメッシュに合わせて、自動的にバッファのサイズを変更します。これは時間のかかる操作です。例えば、デフォルトのバッファサイズより大きいテクスチャを多数ロードしている場合など、Unity が複数回実行しなければならない場合は特に時間がかかります。Unity がバッファサイズを変更しなければならない回数を減らすために、この値を、ロードすると予想される最大の値に合わせて設定してください。これは通常、シーン内の最大のテクスチャの値です。

この値は、Quality settings ウィンドウか、QualitySettings.asyncUploadBufferSize API を使用して設定できます。

非同期アップロードタイムスライス

Async Upload Time Slice は、CPU が GPU にテクスチャやメッシュデータをアップロードするのに費やす時間を、フレームあたりのミリ秒で表したものです。

値が大きいほど、データが GPU 上ですぐに準備できることを意味しますが、CPU はそれらのフレームの間、アップロード操作に多くの時間を費やします。Unity がこの時間をアップロードに使うのは、GPU へのアップロードを待っているデータがバッファにある場合だけです。待機中のデータがなければ、Unity はこの時間を他の操作に使うことができます。

この値は、Quality settings ウィンドウで設定するか、QualitySettings.asyncUploadTimeSlice API を使用して設定できます。

その他の情報

テクスチャやメッシュデータの非同期アップロードの詳細については、Unity ブログの Async Upload Pipeline (AUP) でローディングのパフォーマンスを最適化する を参照してください。

CullingGroup API
グラフィックスパフォーマンスの最適化