Open level taking a really long time (strange)

I am having a weird issue. i have a vr project using the vr expansion plugin.

when i open the project, i hit vr preview and everything works fine, i use a button press to re open the level i am currently on and everything works fine BUT ONLY THE FIRST TIME I HIT VR PREVIEW. every time after that, the level takes forever to re-open. if i close and reopen the project , same thing. the first time i use vr preview everything works as it should and i can restart the level as many times as i want and it opens very quickly. , but after that it freezes up or lags for a long time before reopening the level. what could possibly be going on?

I’ve spent a long time debugging this issue and I have some comments that will hopefully help the Epic devs:

This occurs in a freshly created VR template in 4.18 and 4.19 (I haven’t tried an earlier version).I am using an Oculus, I am not sure if this issue is present on the Vive. This issue is not present when using a non-VR PIE mode.

To reproduce add a OpenLevel node to the playercontroller on a keypress to have it open another level from the start level. Start the game in a VR preview and press the key to open the next level. When the load has finished close the PIE VR preview and start it again and repeat the process. The second time (and all subsequent times until the editor is restarted) the load will hang for a very long time and the HMD screen will freeze with a timer icon over it (different from fading to black during a normal load).

The hang is always exactly 30 or 60 seconds (+ 1 or 2 for normal load delays), suggesting to me there’s some hangup that’s only resolved when the garbage collector first kicks in. It seems the game thread is being blocked by the rendering thread which is being blocked from flushing some cached resources from the previous run.

I have one project pretty far into development that does not have this issue unlike other projects. I’m still trying to work out why it’s not present in that project. Here is a stat profile file for the profiler loading from one empty level into another (to isolate the issue) that demonstrates this problem (just find the 30000ms spike in the middle!).

Relevant stack trace:

    FEventWin::Wait
    GameThreadWaitForTask (in RenderingThread.cpp)
    FRenderCommandFence::Wait(bool)
    FlushRenderingCommands()
    UTexture::ReleaseResource()
    UTexture::UpdateResource()
    UObject::SetLinker(FLinkerLoad * LinkerLoad, int LinkerIndex, bool bShouldDetachExisting)
    FLinkerLoad::FindExistingExport(int ExportIndex)
    FLinkerLoad::FindExistingExport(int ExportIndex)
    FLinkerLoad::FindExistingExports()
    FLinkerLoad::Tick(float InTimeLimit, bool bInUseTimeLimit, bool bInUseFullTimeLimit)

Temporary workaround fix:

To fix the issue you have you call ShowSplashScreen before you call OpenLevel. Make sure your GameInstance calls SetSplashScreen (and get some nice splash screen texture to use). You’ll probably just do this in its Init function. You can also call EnableAutoLoadingSplashScreen for convenience, but the auto splash screen won’t be enough to fix it on its own because it will turn on too late. Then you’ll need to call HideSplashScreen once the level has loaded (in my case I do it once the local player has possessed a pawn in the level). Make sure you don’t ever miss the HideSplashScreen call or you can end up in a situation where the player just sees the loading splash screen indefinitely.

Debug Info (Please also see my initial comments under the OP):

I figured out why my project didn’t have the issue. If you have a VR loading splash screen enabled when you start loading the level it’ll prevent the hang from happening. I believe this is because the bug is due to something the HMD is rendering not being unloaded properly when the next map starts loading which locks up the rendering thread (which locks up the game thread in GameThreadWaitForTask) until the GC finally removes the object causing the block (obviously this explanation is missing a lot of technical detail since I haven’t looked at the HMD rendering code but hopefully I’m in the right ballpark). Also, the issue is present in 4.18 but seems relatively new anyway so I’m wondering if there was some recent change in the Rift’s drivers that made this issue pop up suddenly. Just a random guess, it would be helpful to know if you are using a Rift too.

Note that this bug occurs even if you’re loading an empty pawn into an empty map and it only occurs in a VR preview in editor due to this code in UObject::SetLinker

if (bShouldDetachExisting)
    {
#if WITH_EDITOR
        PostLinkerChange();
#else

The UObject is a Texture in this case and PostLinkerChange triggers ReleaseResource on it and that release seems to be where the block is.

I’m guessing this fixes the issue because it stops rendering everything but the splash screen texture, so whatever resource or process would otherwise lock up the rendering thread during loading was already hidden/stopped by the splash screen. I hope this is helpful and hopefully Epic will weigh in soon.

hey wow that worked
THANKS!!!

Wow, thanks a lot! I was having exactly the same issue, this worked perfectly!

Thanks a lot for the fix!

Even simpler repro steps:

  1. Create a minimal C++ project
  2. Include HeadMountedDisplay in the PublicDependencyModuleNames.
  3. Open a level with UGameplayStatics::OpenLevel() or blueprint.

This is still an issue in 4.19.2.

Thanks for this fix, it’s really helpful.

Necro-Post, thanks a lot @hdelattre, this was the fix I needed. I’ve seen this in the past but it went away with updates. Now with the latest Oculus 4.22.3 it seems to be back but this fix worked!

also… dont exit your game with esc button… set up a key bind with quit game…

Hey, Ive been having the same problem in 4.24.
I found the answer in another forum. What causes the problem is the auto-enabled splash screen setting in the Oculus VR section. If you turn it off, its fine

Taking tips from “hdelattre” answer, i narrowed it down to that:

  1. Added ShowLoadingScreen at Init method in gameinstance
  2. Added delay(0,1 sec was enough for me) and HideLoadingScreen into pawns BeginPlay method