Shader Prewarming Workflow for VR

Hello all,

For reference, my editor / graphics set up is:
Unity 2021.3.37f1, Android targeting Quest 2 / 3, Open GLES3, Built-In Render Pipeline (Not URP, whatever were calling the one with no Render Pipeline Asset)

Ive been fighting an issue with large performance hitches whenever an object is being rendered for the first time, due to the shader being compiled.
Ive gone through the process of playing the scenes in editor, saving the tracked shader variants to a collection, then warming them up when loading that level by calling WarmUp() on that shader variant collection.
Im still seeing the performance hit when loading these scenes despite this, and have found from searching the forums that Unity fails to add the STEREO_MULTIVIEW_ON keyword for shaders.

When tracking the shader variants via editor playmode, I am seeing variants with STEREO_INSTANCING_ON. Ive read in other forum posts that the workaround for this is to manually edit the SVC file to add STEREO_MULTIVEW_ON (which is crazy), but Im not sure if I need to add a new entry into the variants list that is the same as the one with stereo instancing on, but with stereo multiview on added, or if I should replace “STEREO_INSTANCING_ON” with “STEREO_MULTIVIEW_ON”.

[Original shader variant example]


[Add new entry with STEREO_MULTIVEW_ON]

[Replace “STEREO_INSTANCING_ON” with “STEREO_MULTIVIEW_ON”]

Im also trying to figure out how to log when these shaders are being compiled on device at run time. Ive checked the Log Shader compilation box in the Graphics settings, set build mode to Development, then clicked Build and Run. The editor console does connect to the Quest and gives logs, but I dont see any logs that say "Compiled Shader: "; instead I see

“AndroidPlayer “Oculus_Quest 2@ADB:1WMHHB401V2212:0” Uploaded shader variant to the GPU driver: MK/Toon/Built-in/Standard/Physically Based, pass: ForwardAdd, stage: all, keywords POINT STEREO_MULTIVIEW_ON _MK_ALBEDO_MAP _MK_ARTISTIC_ANIMATION_STUTTER _MK_DETAIL_BLEND_MIX _MK_DIFFUSE_MINNAERT _MK_LIGHT_BANDED _MK_PBS_MAP_0 _MK_PBS_MAP_1 _MK_RIM_SPLIT _MK_SPECULAR_ISOTROPIC”

Im not sure if this is different than compilation or what, but the performance stall is definitely happening while this is getting logged.

Ive seen this forum post but Im still unclear on the proper way to view the shader compilation logs:

The main question is: What the heck is the “proper” way to warm up shader variants to avoid this hitch??
From my research the intended workflow is to:

  • Clear tracked shader variants in graphics settings
  • Play the scene with the shaders in it in editor
  • Save those tracked shaders to an SVC
  • During runtime, call WarmUp() on that SVC when loading that scene

This is exactly what Im doing yet Im still getting the stalls.

Ive also read about flying a dummy camera through the level while loading to force the rendering of objects and thus trigger compilation of shaders, but thats just so incredibly hacky Im hoping theres a better way.

The ways that I could be potentially messing this up are:

  • The shaders in my SVC that get prewarmed on level load are in an asset bundle (Im splitting application binary so there is an obb file but I have no idea how to check if the shaders in the SVC are in the main apk or the obb)
  • Some combination of the STEREO_MULTIVIEW_ON needing to be added or whatever

For my sake, and Im sure many others suffering from this, some consensus on the best way to handle this would be extremely appreciated!
Thanks

2 Likes

For those interested, replacing STEREO_INSTANCING_ON with STEREO_MULTIVIEW_ON seems to work. Its a bit sketchy as I definitely tried it a few times and didnt see results, but after trying several other things which didnt work, then trying again, it seems successful. Still investigating, will follow up with more results.

1 Like