ランタイム PSO 事前キャッシュ システム では、PSO コンピレーション中にゲームにヒッチが起こることを防ぐのに十分ですが、事前に作成された PSO キャッシュをゲームにバンドルしたい場合があります。
このドキュメントでは、PSO キャッシュの生成プロセスについて説明します。このドキュメントに記載されている情報は、グラフィック PSO 収集にのみ関するものです。コンピュート シェーダーは、プロジェクトをクックするときに自動的にコンピューティング PSO を生成します (r.ShaderPipelineCacheTools.IncludeComputePSODuringCook CVar によって管理されフィルタリング ルールに従います)。レイトレーシング PSO のキャッシュのバンドルはサポートされていません。
記録されたキャッシュおよび安定したキャッシュ
PSO 内で最も重要なデータは、シェーダー情報です。ただし、Unreal Engine のシェーダーは、デベロッパーがマテリアルを微調整するため、複数のビルド間で変更される可能性があります。ゲームを長時間プレイした後に PSO キャッシュがすべて破棄されないように、PSO キャッシュ ファイルは次の 2 種類に分けられます。
-
記録された PSO キャッシュ (
.upipelinecache
ファイル)。これらは、アプリケーションのビルドを実行する際に記録されます。記録されたキャッシュ内のシェーダーは、バイトコードの SHA ハッシュによって識別されます。
-
安定した PSO キャッシュ (
.spc
ファイル)。これらは、マップ ファイルをクックするときに生成され、デベロッパーがプロジェクト内のマップやシェーダーを変更したときに、予想どおりに変更されるシェーダー情報が含まれています。
これらの情報は、マテリアル名、頂点ファクトリ名、シェーダー タイプなど、複数のビルド間で同一であることが想定される安定した高レベルの記述によって識別されます。この記述は「安定キー」と呼ばれ、.shk
ファイルで表されます (バージョン 5.x 以前の Unreal Engine では、.scl.csv
ファイルで表されていました)。
これにより、記録されたデータが頻繁な変更に対して比較的堅固な状態を保証されます。アプリケーションにきわめて大きな変更がある場合は PSO キャッシュの再記録が必要になることがあるものの、アプリケーション全体の内容が確定したら、PSO キャッシュをそのままにしておくことができます。
各種プラットフォームおよびグラフィック API における PSO
このドキュメントで説明されているキャッシュには、高レベルの PSO 記述が含まれています。この PSO 記述は、エンジンのコードでは FGraphicsPipelineStateInitializer
にマップされます。ただし、PSO データはあらゆる状況に対応できるわけではありません。Unreal Engine の各 Rendering Hardware Interface (RHI) は異なるプロパティを持ち、異なるレンダリング パスを実行することができます。
このため、PSO キャッシュの内容は、プラットフォームやレンダリング レベルによって異なります。これらの PSO キャッシュ間の情報は、互換性がありません。たとえば、D3D12 RHI で実行されているゲームで収集されたキャッシュは、Vulkan で実行されている同じゲームでは使用できません。
複数のグラフィックス API を使用できるプラットフォームでシッピングし、アプリケーションでそういった API を選択できるようにする場合は、ビルドに複数のキャッシュ ファイル (API ごとに 1 つ) を含める必要があります。たとえば、Android では、執筆時点で、OpenGL ES が該当する API として保持されています。Android で GLES および Vulkan の両方を使用してアプリケーションをシッピングする場合、RHI ごとに 1 つ、計 2 つのキャッシュ ファイルを収集して、含める必要があります。
GLES には、PSO の概念がありません。代わりに、「プログラム オブジェクト」という類似の概念を使用します。
固定ハードウェアを使用するプラットフォームには、通常、この高レベル PSO キャッシュは不要で、このキャッシュで得られるメリットもありません。つまり、固定ハードウェアを使用するプラットフォームは、独自のソリューションを備えているか、ランタイム パフォーマンスのペナルティを完全に回避することができます。そういったプラットフォーム向けに開発する場合は、特定のプラットフォームのドキュメントを参照してください。
D3D11 などのレガシー API も、このキャッシュではサポートされていません。
収集フロー
このセクションでは、PSO キャッシュのデータ収集を、事前に記録されたキャッシュが含まれていないビルドで、ゼロから始めることを前提としています。PSO キャッシュの収集プロセスは反復的に実行されます。つまり、白紙の状態から始めるのではなく、時間の経過とともに、以前のデータを喪失することなく、PSO キャッシュにデータを追加していくことができます。ただし、キャッシュ ファイルが古い場合は、通常、PSO キャッシュを再生成することをお勧めします。これは、最初に収集したときからコードまたはコンテンツが大幅に変更されると、その内容が適切ではなくなることがあるためです。キャッシュに古い PSO があると、それらの PSO はコンパイルされますが使用されることはないため、不必要にロード時間が長くなります。
Flow chart depicting the collection cycle for PSO caches. Click image to enlarge.
以降のセクションでは、PSO キャッシュを収集して、プロジェクトに実装するために必要な手順について説明します。
セットアップおよび必須の設定
プロジェクトで PSO キャッシュを記録するように設定するには、次の手順を実行します。
- プロジェクトの
DefaultEngine.ini
か、その(Platform)Engine.ini
を開きます。
「(Platform)Engine.ini
」ファイルは通常、「(Project)/Config/(Platform)
」ディレクトリに格納されています。このディレクトリを使用すると、PSO キャッシュを必要としない可能性のある他のプラットフォームがこの設定を取得するのを防ぐことができます。
-
「
Engine.ini
」ファイルで次の値を設定します。[DevOptions.Shaders] NeedsShaderStableKeys=true
-
「
DefaultGame.ini
」ファイルで、次の値を設定します。[/Script/UnrealEd.ProjectPackagingSettings] bShareMaterialShaderCode=True bSharedMaterialNativeLibraries=True
-
ゼロから始める場合は、「
(Project)/Build/(Platform)/PipelineCaches
」にファイルがないことを確認します。これは、クッカーが記録されたキャッシュ ファイルを検索する場所です。PSO を初めて収集するときは、このフォルダが存在しない可能性があります。 -
CVar
r.ShaderPipelineCache.Enabled
が「1」に設定されていることを確認します。
記録された PSO キャッシュを収集する
PSO キャッシュを記録するには、次の手順を実行します。
-
パッケージ化されたアプリケーションを
-logPSO
コマンドライン スイッチを指定して実行します。 -
アプリケーションのパスをできるだけたくさん実行します。たとえば、アプリケーションのすべてのレベルをプレイし、グラフィック設定を変更します。
-
アプリケーションを実行するたびに、
Saved/CollectedPSOs
に記録されたキャッシュ ファイル (rec.pipelinecache
) が生成されます。それらを収集して、コンピュータの任意の場所にある新しいディレクトリに配置します。このガイドでは、ディレクトリ「C:\PSOCache
」を使用します。
記録された PSO キャッシュを収集する際の最終目標は、アプリケーションでユーザーに表示される可能性のあるすべてのマテリアルやビジュアル エフェクトを確認することです。そのため、できるだけ多くの場所にアクセスして、さまざまなグラフィック設定の組み合わせを使用して、マテリアルやエフェクトを徹底的に確認する必要があります。
なお、一度の実行ですべての PSO キャッシュを収集する必要はありません。アプリケーションの開発中に複数回実行することもできますし、この作業を複数人で分担して行うこともできます。記録された PSO キャッシュは、手動で削除するまで削除されないため、開発中に徐々に蓄積していくことができます。
PSO キャッシュを変換する
前の手順で作成した PSO データを有用な形式に変換するには (「拡張」とも呼ばれます)、次の手順を実行します。
-
プロジェクトのコンテンツをクックします。これを実行するためには、アプリケーションをパッケージ化します。
-
(Project)/Saved/Cooked/(Platform)/(ProjectName)/Metadata/PipelineCaches
を開きます。安定したシェーダー キー (.shk
) ファイルをこのディレクトリから、rec.pipelinecache
ファイルを格納したフォルダにコピーします。たとえば「C:\PSOCache
」です。 -
ShaderPipelineCacheTools
コマンドレットを以下の引数で実行します (現在のディレクトリが以下のエンジンのインストール ディレクトリであることを前提とします)。
Engine\Binaries\Win64\UnrealEditor-Cmd.exe -run=ShaderPipelineCacheTools expand C:\PSOCache\*.rec.upipelinecache C:\PSOCache\*.shk C:\PSOCache\[YourPrefix][ProjectName][ShaderFormatName].spc
ファイル名には、次のものを含める必要があります。
- (YourPrefix):任意の文字列。通常は、収集が実行されたタイミングを指定します。たとえば、これは現在のビルドのチェンジリストである可能性があります。
- (ProjectName):プロジェクトの名前。例:ShooterGame。これは、プロジェクトの名前と厳密に一致している必要があります。一致していない場合、取得されません。
- (ShaderFormatName):プロジェクトのシェーダー形式。シェーダー形式の名前と正確に一致している必要があります。D3D12 の場合、これは
PCD3D_SM6
になります。
上記の規則を使用したプロジェクト ShooterGame の完全名は、「CL11122333_ShooterGame_PCD3D_SM6.spc」です。
アプリケーションに PSO キャッシュを含める
-
前のセクションで作成した
.spc
ファイルを「Build/[PlatformName]/PipelineCaches
」フォルダに格納します。たとえばBuild/Windows/PipelineCaches
です。 -
プロジェクトを再度クックするか、パッケージ化します。PSO キャッシュ ファイルがクッカーによって取得される必要があります。また、ログには末尾付近に以下のような内容が含まれています。
LogCook: Display: ---- Running UShaderPipelineCacheToolsCommandlet for platform WindowsClient shader format PCD3D_SM6 LogCook: Display: With Args: build "../../../TestGame/Build/Windows/PipelineCaches/*TestGame_PCD3D_SM6.spc" "d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Metadata/PipelineCaches/ShaderStableInfo-Global-PCD3D_SM6.shk" "d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Metadata/PipelineCaches/ShaderStableInfo-TestGame-PCD3D_SM6.shk" "d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Content/PipelineCaches/Windows/TestGame_PCD3D_SM6.stable.upipelinecache" LogShaderPipelineCacheTools: Display: Sorting input stable cache files into chronological order for merge processing... LogShaderPipelineCacheTools: Display: Loading d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Metadata/PipelineCaches/ShaderStableInfo-Global-PCD3D_SM6.shk... LogShaderPipelineCacheTools: Display: Loading d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Metadata/PipelineCaches/ShaderStableInfo-TestGame-PCD3D_SM6.shk... LogShaderPipelineCacheTools: Display: Loaded 3554 shader info lines from d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Metadata/PipelineCaches/ShaderStableInfo-Global-PCD3D_SM6.shk. LogShaderPipelineCacheTools: Display: Loaded 3833694 shader info lines from d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Metadata/PipelineCaches/ShaderStableInfo-TestGame-PCD3D_SM6.shk. LogShaderPipelineCacheTools: Display: Loaded 3837248 unique shader info lines total. LogShaderPipelineCacheTools: Display: Loaded 13238 stable PSOs from ../../../TestGame/Build/Windows/PipelineCaches/++Test+GoldMaster-CL-17412694-TestGame_PCD3D_SM6.spc. 2329 PSOs rejected, 5840141 PSOs merged LogShaderPipelineCacheTools: Display: Re-deduplicated into 35084 binary PSOs [Usage Mask Merged = 3]. LogShaderPipelineCacheTools: Display: Running sanity check (consistency of vertex format). LogShaderPipelineCacheTools: Display: 0 vertex shaders are used with an inconsistent vertex format LogShaderPipelineCacheTools: Display: === Sanitizing results === LogShaderPipelineCacheTools: Display: Before sanitization: .................................................................... 35382 PSOs LogShaderPipelineCacheTools: Display: Filtered out due to inconsistent vertex declaration for the same vertex shader:.......... 0 PSOs LogShaderPipelineCacheTools: Display: Filtered out due to VS being possibly incompatible with an empty vertex declaration:..... 1 PSOs LogShaderPipelineCacheTools: Display: ----- LogShaderPipelineCacheTools: Display: Number of PSOs after sanity checks:...................................................... 35381 PSOs LogShaderPipelineCacheTools: Display: Wrote 35381 binary PSOs (graphics: 34834 compute: 547 RT: 0), (18453KB) to d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Content/PipelineCaches/Windows/TestGame_PCD3D_SM6.stable.upipelinecache LogCook: Display: ---- Done running UShaderPipelineCacheToolsCommandlet for platform WindowsClient
これが動作していることを確認するには、ログの末尾に書かれている、バイナリ PSO の書き込み数を示す行を確認します。この行のグラフィック PSO の数は 0 より大きい必要があります。
LogShaderPipelineCacheTools: Display: **Wrote 35381 binary PSOs** (graphics: 34834 compute: 547 RT: 0), (18453KB) to d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Content/PipelineCaches/Windows/TestGame_PCD3D_SM6.stable.upipelinecache LogCook: Display: ---- Done running UShaderPipelineCacheToolsCommandlet for platform WindowsClient
PSO のカバレッジをテストする
PSO キャッシュのカバレッジが十分であるかどうかを判断するには、新しくパッケージ化されたアプリケーションを -logpso
コマンドで実行し、ログ出力を観察してください。次のような行が表示されます。
[2021.10.06-20.06.22:848][ 0]LogRHI: Opened FPipelineCacheFile: ../../../ShooterGame/Content/PipelineCaches/Windows/ShooterGame_PCD3D_SM6.stable.upipelinecache (GUID: EA50968D47BDE9A04A8524BCEB51615D) with 269 entries.
この数字は、パッケージ化ログに書かれているバイナリ PSO の数と一致している必要があります。たとえば、ログに 35381 個のバイナリ PSO を書き込んだとレポートされている場合、35381 個のエントリが表示されると予想されます。
また、ビルドのログに「Encountered a new graphics PSO」と出力されているかどうかも確認する必要があります。キャッシュの収集時と同じ条件 (同じスケーラビリティ設定など) で同じ内容が表示されている場合は、この状況が発生することはありません。
キャッシュをパーティショニングする
執筆時点では、結果として得られる PSO キャッシュは、ゲームのビルドに含まれている単一のモノリシック ファイルです。ゲームのデフォルトの動作では、起動時にこのファイルを開き、そのファイルから PSO のコンパイルを開始することを試行します。ただし、すべての PSO が常に適切であるわけではありません。たとえば、あるものは別のレベルから収集されたものである可能性がありますし、あるものは異なるグラフィック設定で記録されたものである可能性があります。
それらすべてを不必要にコンパイルすることを避けるため、現在、各 PSO は「ゲーム使用状況マスク」と呼ばれるビットマスクと関連付けられています。アプリケーションは SetGameUsageMaskWithComparison
関数を使用して、異なるレベルまたは異なるグラフィック (品質) 設定で記録された PSO をコンパイルしないようにすることができます。以下は、そのような関数の例です。
void SetPSOCacheUsageMask(int32 QualityLevel, int32 MapIndex)
{
uint64 GameMask = 0;
const int32 kMaxQualityLevels = 4;
GameMask |= (1ULL << static_cast<uint64>(QualityLevel));
check(MapIndex < 64 - kMaxQualityLevels);
GameMask |= (1ULL << static_cast<uint64>(kMaxQualityLevels + MapIndex));
// デフォルトのビット単位の AND 比較が機能するため、比較関数をオーバーロードする必要はありません
FShaderPipelineCache::SetGameUsageMaskWithComparison(GameMask);
}
ゲーム内に 60 以上のマップがある場合、またはより細かい品質設定をエンコードする必要がある場合は、uint64 を複数のビットフィールドの構造体として処理し、カスタム比較関数を使用して比較するなど、別の方法でマスクを生成することができます。次に例を示します。
union
{
uint64 Packed;
struct
{
uint64 MaterialQuality : 4;
uint64 ShadowQuality : 4;
uint64 MapIndex : 16;
};
};
この関数は、ユーザー設定 (UGameUserSettings
) のロード/セーブ時など、起動時の早い段階でアプリケーションによって設定される必要があります。以下の各ケースで使用されます。
-
記録処理中、記録された PSO は、現在の使用状況マスクと関連付けられます。
-
コンパイル中、現在の使用状況マスクに一致する PSO のみがキャッシュからコンパイルされます。
コンパイルは非常に早い段階で開始されるため、デフォルトでは「paused」で開始し (下記参照)、正しいマスクが設定された後に明示的に再有効化することをお勧めします。
制限および今後の課題
現在のところ、マスクの概念は本質的に手動での収集に依存しています。対照的に、クック中に自動的にキャッシュに追加されるコンピュート PSO は、すべて 0xffffffffffffffff
(すべて 1) のマスクを持っています。PSO キャッシュのプログラムによる作成を実装することは、(一部の) グラフィック PSO にも自動キャッシュを適用することを意味し、ユーザー マスクの概念は別のアプローチに発展するか、完全に廃止される可能性があります。
ゲーム コンテンツが複数のダウンロードに分かれている場合、PSO キャッシュを独立したコンテンツのバンドルに対応するチャンクに分割することは困難です。
このドキュメントではキャッシュの分割について説明していません。キャッシュの分割の詳細については、「クック処理とチャンク化」を参照してください。
PSO コンパイルを制御する
キャッシュに含まれる PSO は、レンダリング コードが必要とするときにすぐに使用できるように、コンパイルする必要があります。デフォルト設定を使用した新規プロジェクトでは、アプリケーションの起動後、バンドルされている PSO キャッシュ ファイルが自動的に開かれ、コンパイルが自動的に開始されます。これが望ましくない場合 (カスタム使用状況マスクを設定する必要がある場合など)、r.ShaderPipelineCache.StartupMode=0
を使用してコンパイルを一時停止し、その後、FShaderPipelineCache::ResumeBatching()
でコンパイルを再開することができます。
PSO のコンパイル時には次の複数の起動モードを使用できます。
値 | モード | 説明 |
---|---|---|
0 | Paused (一時停止) | コンパイルが再開されるまで中断されます。 |
1 | Fast (高速) | 画面などのゲームの非インタラクティブな部分のロード時は、高速モードを使用することをお勧めします。 |
2 | Background (バックグラウンド) | バックグラウンド モードは、プレイヤーが UI を操作している間にコンパイルするのに適しています。 |
3 | Precompile (プリコンパイル) | Fast と Background の両方のプロパティを兼ね備えています。個別のプリコンパイル使用状況マスク (r.ShaderPipelineCache.PreCompileMask で設定) を使用して、それに一致する PSO を Fast モードでコンパイルし、(通常の使用状況マスクにのみ一致する) その他の PSO は Background モードでコンパイルします。 |
また、コンパイルが完了するまで、ロード画面をより長く表示したい場合は、FShaderPipelineCache::NumPrecompilesRemaining()
を呼び出してコンパイルする未処理の PSO の数をクエリすることもできます。
モードにはより細かい設定があり、プリコンパイルに一度にかかるバッチのサイズや、フレームごとにプリコンパイルにかける目標時間を設定することができます。PSO のコンパイルにかかる実際の時間は、ゲームで制御することはできません。
ユーザー キャッシュ ファイル
PSO キャッシュをゲームと一緒に提供しても、収集時にカバーされていないコンテンツが含まれていることがあります。ドライバによっては独自のキャッシュを提供できるものもありますが、ドライバの動作からさらに独立するために、ゲームは、デフォルトでは、不足している PSO を収集し、ローカル ユーザー キャッシュ ファイルに保存することを試みます。これらはゲームの「Saved
」ディレクトリ (FPaths::ProjectSavedDir()
) に格納されており、ゲームのユーザー設定と同じディレクトリにあります。アプリケーションは起動時にこれらのユーザー キャッシュをロードし、その内容をビルドに含まれるファイルにマージします。
ユーザー キャッシュ PSO ファイル形式は記録されたキャッシュです。つまり、この形式は、SHA ハッシュを使用してシェーダーを参照し、多くのコンテンツを変更する大規模なゲーム更新の際には使用できません。そのため、各ファイルには「ゲームのバージョン」が埋め込まれています。これは、実行中のアプリケーションと照合されます。ゲームのバージョンは、以下の例のように「DefaultGame.ini
」で設定され、コンテンツの変更やレンダリング コードの大幅な変更を含むアップデートなど、アプリケーションが互換性のない可能性のあるアップデートを発行するたびに、バージョン番号を上げる必要があります。
[ShaderPipelineCache.CacheFile]
GameVersion=1234
デフォルトでは、GameVersion
は EngineVersion
から取得されます。EngineVersion は通常 Perforce のチェンジリストを緊密に追跡しているため、2 つの異なるビルドで書かれたユーザー キャッシュ (関連する変更がない場合でも) の互換性は失われます。
キャッシュ ファイルが無制限に大きくなるのを防ぐため、アプリケーションはロード時に直ちにキャッシュ ファイル内のエントリをガベージ コレクションします。これは、エントリの最終使用時間に基づいており、CVar r.ShaderPipelineCache.UserCacheUnusedElementRetainDays
を使用して設定可能です。デフォルト値は 30 日です。
Vulkan および OpenGL ES RHI は、RHI 内に独自の低レベルのパイプライン キャッシュを含んでいます。PSO がコンパイルされた後 (ソースがキャッシュであるか、コードによる作成かにかかわらず)、そのキャッシュに保存され、次回の起動時に取得されます。これらのグラフィックス API を使用する場合、ユーザー キャッシュ ファイルを有効にする必要はない場合があります。
手動の PSO キャッシュとランタイム PSO 事前キャッシュ間のインタラクション
ランタイム PSO 事前キャッシュ システム が有効な場合、手動で収集したキャッシュのビルドが必要なくなることがわかります。ただし、手動でビルドした PSO キャッシュを収集してシッピングした方がメリットがある場合もいくつかあります。次のオプションを使用すると、PSO の事前キャッシュが有効になっている場合に、手動キャッシュ システムの動作を微調整することができます。
CVar | 説明 | デフォルト設定 |
---|---|---|
r.ShaderPipelineCache.ExcludePrecachePSO |
PSO 事前キャッシュ システムによって欠落した PSO のみをキャッシュで収集するかどうかを制御します。これにより、欠落した PSO のみをターゲットとする整ったキャッシュが可能になります。ただし、このオプションを利用するには r.PSOPrecache.Validation を設定する必要があります。 |
Disabled (無効) |
r.ShaderPipelineCache.OnlyOpenUserCache |
バンドルされたキャッシュのロードを無効にしますが、ユーザー キャッシュは引き続き開きます。PSO キャッシュ ファイルを含めるシッピングは計画していないが、ユーザーがゲームをプレイする際に PSO キャッシュを収集できるようにしたい場合に適したオプションです。 | Disabled (無効) |
FAQ
PSO はどのくらいの頻度で収集する必要がありますか?
コンテンツが大幅に追加、更新、または変更されるたびに、プロジェクトの PSO データをリキャプチャーするのが理想的ですが、実際は開発が急速に進行することから、不可能です。プロジェクトごとに PSO の収集要件は異なるため、厳密なスケジュールを設定することはできません。経験則としては、ビルドで頻繁にヒッチが発生するようになったと感じた場合は、PSO キャッシュを更新する必要があります。特に、最新のキャッシュを持たないビルドのパフォーマンスは絶対に測定しないでください。あるいは、少なくとも、その測定値を比較に使用しないでください。
特別な PSO キャッシング レベルを作成する必要がありますか?
プロジェクトの標準レベルから必要なすべての PSO データをキャプチャできますが、一部のプロジェクトでは特別な PSO キャプチャ レベルを作成することでメリットが得られる場合があります。これらのレベルは、特定のタイプのすべてのアセットをスポーンし、PSO データをキャプチャするように設定できます。特別な PSO キャプチャ レベルの作成は、ロック解除に時間がかかるコンテンツや動的にスポーンされるコンテンツがプロジェクトにある場合に特に有効です。
私は PSO を収集していませんが、ビルドには PSO キャッシュがあるようです。
Niagara コンテンツがあれば、これは想定されることです。コンピュート PSO は、(プロジェクトのキャッシュを有効にした場合) クック プロセス中に自動的にキャッシュに追加されます。
ビルドに PSO キャッシュがありますが、依然としてゲームでヒッチが発生します。
まず、以下を確認します。
-
ゲームはキャッシュでサポートされているグラフィック API (D3D11「ではなく」、D3D12 など) で実行されています。
-
このファイルはゲームの起動時に開かれます。
-
適切な PSO がバックグラウンドでコンパイルされています。
これを行うには、ログ ファイルを調べて、LogRHI ロギング カテゴリを探します。次のような行が表示されることを確認します。
LogRHI:908 エントリを含む FPipelineCacheFile: ../../../TestGame/Content/PipelineCaches/Windows/TestGame_PCD3D_SM6.stable.upipelinecache (GUID: 91C5586843C2B5CEE3F4F7BE47E71253) を開きました。
LogRHI:表示:状態変更後にパイプライン キャッシュを開き、事前コンパイルに 908 個のタスクのうち 908 個がエンキューされました。
エントリとタスクの数は異なりますが、0 以外である必要があります。
次に、新しい PSO が何個検出されるかを確認します。これには、-logPSO コマンドライン スイッチを指定して (またはユーザー キャッシュ ファイルを有効にして) ビルドを実行し、次のような行がどのくらいの頻度で表示されるかを確認します。
LogRHI:表示:新しいグラフィック PSO: 4233039161 が発生しました。
PSO:
の後に表示される数字は異なります。かなりの数が表示され、その出現がヒッチと一致する場合は、キャッシュに問題がある可能性があります。現在のコンテンツで再度キャッシュを収集してください。一からやり直す必要がある場合があります。
これらの行が出現しない場合、または D3D11 で実行しているものの、ビルドがヒッチする場合、ヒッチは PSO とは直接関係ない可能性があります。その場合、CPU プロファイラを使用してゲームをプロファイリングして、ヒッチの性質を理解することをお勧めします。