UE4 Shader Pipeline Cache に乗っていないシェーダーを調査する


Shader Pipeline Cache とは

シェーダーは GPU に投入される前に、シェーダーコードをシェーダーバイナリへコンパイルする必要があります。 Shader Pipeline Cache は、コンパイル済みシェーダーバイナリをメモリ上にキャッシュし、次に利用する際にキャッシュ済みシェーダーバイナリを再利用する機能です。
事前にシェーダーリストを生成し、ゲーム起動時やローディングの合間にコンパイルすることができます。
https://docs.unrealengine.com/en-us/Engine/Rendering/PSO-Caching

キャッシュされていないシェーダーが使われる場合、次のように大きくヒッチが発生します。

シェーダーリストの生成

実際にシェーダーが使われる前にシェーダーをコンパイルするには、シェーダーリストが必要となります。このシェーダーリストを生成するには、実際にゲームをプレイし、シェーダーをコンパイルしたログを収集することになりますが、言うまでもなくとても面倒な作業となります。
そこで、次の画像のようにゲーム中に動的にスポーンされるマテリアルをアサインしたメッシュを並べたレベルを作成し、このレベルでシェーダーコンパイルのログを収集することにしました。

レベルのライティング環境や、メッシュのライティング設定、アサインしたコンポーネント( InstancedStaticMeshComponent など)によってシェーダーは変わります。

リスト漏れシェーダーを探す

上記のようにシェーダーのプリコンパイルを行っても、実際にはリストの漏れが原因で、シェーダーコンパイルによるヒッチが発生したりします。
原因のシェーダーを探すには、シェーダーのハッシュをログに出力します。

Engine/Source/Runtime/OpenGLDrv/Private/OpenGLShaders.cpp
// Link program, using the data provided in config
LinkedProgram = LinkProgram(Config, bFromPSOFileCache);

UE_LOG(LogRHI, Warning, TEXT("not found LinkedProgram: VertexShaderHash( %s ), PixelShaderHash( %s )"), *VertexShaderRHI->GetHash().ToString(), *PixelShaderRHI->GetHash().ToString());

出力されたシェーダーハッシュを /PATH/TO/PROJECT/Saved/Cooked/PLATFORM/*.scl.csv に存在するクック済みマテリアル情報と照らし合わせ、該当するマテリアルをシェーダーリスト用レベルに追加します。

LogRHI: Warning: not found LinkedProgram: VertexShaderHash( F9B8B3D7AF22F9874B766922B3068F2501856565 ), PixelShaderHash( B26D8EF588701C166A73B52ABF2DBE43543E5FF8 )
% cat ShaderStableInfo-MyGame-GLSL_ES3_1_ANDROID.scl.csv | grep B26D8EF588701C166A73B52ABF2DBE43543E5FF8 | awk -F, '{ print $1 " " $2 " " $9 }'
MaterialInstanceConstant /Game/Item/Weapon/Base/Material/MI_WeaponMat_Default_Base_ORM_Mana.MI_WeaponMat_Default_Base_ORM_Mana TMobileBasePassPSFMobileDirectionalLightCSMAndSHIndirectPolicyINT32_MAXLDRGamma32 FLocalVertexFactory
MaterialInstanceConstant /Game/Item/Weapon/Base/Material/MI_WeaponMat_Default_Base_ORM_Mana.MI_WeaponMat_Default_Base_ORM_Mana TMobileBasePassPSFMobileDirectionalLightAndSHIndirectPolicyINT32_MAXLDRGamma32 FLocalVertexFactory
MaterialInstanceConstant /Game/Item/Weapon/Normal/Material/MI_p_wp_Mid160c.MI_p_wp_Mid160c TMobileBasePassPSFMobileDirectionalLightCSMAndSHIndirectPolicyINT32_MAXLDRGamma32 FLocalVertexFactory
MaterialInstanceConstant /Game/Item/Weapon/Normal/Material/MI_p_wp_Mid160c.MI_p_wp_Mid160c TMobileBasePassPSFMobileDirectionalLightAndSHIndirectPolicyINT32_MAXLDRGamma32 FLocalVertexFactory
...

出力内容は左から、マテリアル名、ピクセルシェーダータイプ、頂点シェーダータイプとなります。