Oculus Quest(Vulkan)でPSOキャッシュを使ってもヒッチが減らせない。OpenGLだとクラッシュする。

Quest向けアプリでPSOキャッシュを使ってみたところ、Vulkanでは効果がなく、OpenGL ES3.1ではクラッシュしてしまいます。

やりたいこと

Oculus(PC)向けに開発していたアプリをOculus Quest向けにポートしようと考えているのですが、Quest上ではパーティクルを動的に生成した際のヒッチが酷かったので以下のスライドや公式ドキュメントを参考にPSOキャッシュを使ってみることにしました。

Vulkanだと効果がない

手順どおり.stablepc.csvファイルを生成していますが、Vulkanを有効にしているとファイル名がMyProject_GLSL_ES3_1_ANDROID.stablepc.csvではパッケージ時に以下のようなエラーがでるので、名前をMyProject_SF_VULKAN_ES31_ANDROID_NOUB.stablepc.scvにしています。

NOT Running UShaderPipelineCacheToolsCommandlet for platform Android_ASTC  shader format SF_VULKAN_ES31_ANDROID_NOUB, no files found at ../../../../../UnrealProjects/MyProject/Build/Android/PipelineCaches/*MyProject_SF_VULKAN_ES31_ANDROID_NOUB.stablepc.csv

デバイスプロファイルやAndroidEngine.iniではr.ShaderPipelineCache.Enabled=1, r.ShaderPipelineCache.StartupMode = 0, NeedsShaderStableKeys=trueに設定し以下のコードをアプリスタート時に実行しています。

FShaderPipelineCache::SetBatchMode(FShaderPipelineCache::BatchMode::Fast);
FShaderPipelineCache::PauseBatching();

FShaderPipelineCache::NumPrecompilesRemaining()を確かめてみると上記のコード実行前は53、実行後は0になっているのでプリコンパイルはされているようなのですが、効果はありませんでした。

実機でPSOデータ収集時には動的にスポーンされるパーティクルを全部スポーンしているのでたぶんデータ収集はうまくいっていると思うのですが、まったくヒッチは減らせませんでした。

追記:stablepc.csvをのぞいてみたところ該当のパーティクルは含まれているようでした。

OpenGL ES3.1ではPSOキャッシングを使うとクラッシュする

Vulkanより安定してそうだと思ったので、VulkanをオフにしOpenGL ES3.1を試してみました。ドキュメントの.stablepc.scv生成の手順を最初からやりなおし、名前はMyProject_GLSL_ES3_1_ANDROID.stablepc.csvとなっています。
これだとローンチはできるのですが、アプリスタート後すぐに下のエラーでクラッシュしてしまいます。プリコンパイルを開始するコードをコメントアウトしてもクラッシュはなおりませんでしたが、r.ShaderPipelineCache.Enabled=0とするとクラッシュはしなくなりましたが、当然PSOキャッシュは使えません。

エラーログ

[2021.01.25-15.42.37:652][  3]LogAndroid: Error: === Critical error: ===
[2021.01.25-15.42.37:652][  3]LogAndroid: Error: 
[2021.01.25-15.42.37:652][  3]LogAndroid: Error: Assertion failed: !ProgramCache.Contains(ProgramKey) [File:D:/Build/++UE4/Sync/Engine/Source/Runtime/OpenGLDrv/Private/OpenGLShaders.cpp] [Line: 2009] 
[2021.01.25-15.42.37:652][  3]LogAndroid: Error: 
[2021.01.25-15.42.37:652][  3]LogAndroid: Error: [Callstack] 0x00000000C8F510EC libUE4.so(0x000000000C28B0EC)!FOpenGLProgramBinaryCache::CompleteLoadedGLProgramRequest_internal(FGLProgramBinaryFileCacheEntry*)  []
[2021.01.25-15.42.37:652][  3]LogAndroid: Error: [Callstack] 0x00000000C8F56208 libUE4.so(0x000000000C290208)!FOpenGLProgramBinaryCache::CheckPendingGLProgramCreateRequests_internal()  []
[2021.01.25-15.42.37:652][  3]LogAndroid: Error: [Callstack] 0x00000000C8F55C40 libUE4.so(0x000000000C28FC40)!FOpenGLProgramBinaryCache::CheckPendingGLProgramCreateRequests()  []
[2021.01.25-15.42.37:653][  3]LogAndroid: Error: [Callstack] 0x00000000C8FC58C0 libUE4.so(0x000000000C2FF8C0)!FOpenGLDynamicRHI::RHIEndDrawingViewport(FRHIViewport*, bool, bool)  []
[2021.01.25-15.42.37:653][  3]LogAndroid: Error: [Callstack] 0x00000000C4FEFB78 libUE4.so(0x0000000008329B78)!FRHICommand<FRHICommandEndDrawingViewport, FRHICommandEndDrawingViewportString1847>::ExecuteAndDestruct(FRHICommandListBase&, FRHICommandListDebugContext&)  []
[2021.01.25-15.42.37:653][  3]LogAndroid: Error: [Callstack] 0x00000000C4FA7ECC libUE4.so(0x00000000082E1ECC)!FRHICommandListExecutor::ExecuteInner_DoExecute(FRHICommandListBase&)  []
[2021.01.25-15.42.37:653][  3]LogAndroid: Error: [Callstack] 0x00000000C50060C0 libUE4.so(0x00000000083400C0)!FExecuteRHIThreadTask::DoTask(ENamedThreads::Type, TRefCountPtr<FGraphEvent> const&)  []
[2021.01.25-15.42.37:653][  3]LogAndroid: Error: [Callstack] 0x00000000C5005780 libUE4.so(0x000000000833F780)!TGraphTask<FExecuteRHIThreadTask>::ExecuteTask(TArray<FBaseGraphTask*, TSizedDefaultAllocator<32> >&, ENamedThreads::Type)  []
[2021.01.25-15.42.37:653][  3]LogAndroid: Error: [Callstack] 0x00000000C383CC60 libUE4.so(0x0000000006B76C60)!FNamedTaskThread::ProcessTasksNamedThread(int, bool)  []
[2021.01.25-15.42.37:653][  3]LogAndroid: Error: [Callstack] 0x00000000C383B198 libUE4.so(0x0000000006B75198)!FNamedTaskThread::ProcessTasksUntilQuit(int)  []
[2021.01.25-15.42.37:653][  3]LogAndroid: Error: [Callstack] 0x00000000C5093198 libUE4.so(0x00000000083CD198)!FRHIThread::Run()  []
[2021.01.25-15.42.37:653][  3]LogAndroid: Error: [Callstack] 0x00000000C3931640 libUE4.so(0x0000000006C6B640)!FRunnableThreadPThread::Run()  []
[2021.01.25-15.42.37:653][  3]LogAndroid: Error: [Callstack] 0x00000000C3836514 libUE4.so(0x0000000006B70514)!FRunnableThreadPThread::_ThreadProc(void*)  []
[2021.01.25-15.42.37:653][  3]LogAndroid: Error: [Callstack] 0x00000000E8223D84 libc.so(0x0000000000047D84)![Unknown]()  []
[2021.01.25-15.42.37:653][  3]LogAndroid: Error: [Callstack] 0x00000000E81F6036 libc.so(0x000000000001A036)![Unknown]()  []

ちなみに、OculusではSupport arm64が推奨されていますが、レベルストリーミングなどに問題があったので代わりにSupport armv7を使用しています。

ヒッチはVRアプリではクリティカルな問題でどうにか減らしたいのですが、PSOキャッシュがうまく動かなくて困っています。なにか解決方法はないでしょうか、よろしくお願いします。

HI! Have you found a solution? I have the same issue with PSO. Also problem at Assertion failed: !ProgramCache.Contains(ProgramKey)

Unfortunately, no.