UE5 and missing performant occlusion culling - is the fix coming soon?

@VictorLerp

As many people are already aware and experienced this issue first hand, UE5 is not yet well suited for mobile VR projects with complex levels as there is no performance-friendly occlusion culling technique present. UE4 had software occlusion culling (along with precomputed visibility culling), which help a ton as it was running on CPU and most more or less complex Quest 2 / Pico 4 projects are GPU bound, which leaves no room for hardware occlusion culling.

Turning off hardware occlusion via cvar in the .ini file does nothing to help performance. In order to bring performance up on Quest 2 with UE5, I had to turn off occlusion culling checkbox in the Project Settings. However, that also disabled precomputed visibility.

Here is a video of a repro case I submitted via bug report form to Epic since 5.0.2 release and never heard back:

Also video shows broken static mesh animated via WPO (no idea if it was fixed in 5.1, still downloading preview 1 :sweat_smile: )

Is there any way you could please find out what are the plans for mobile VR friendly occlusion culling techniques in UE 5.1+ ? Thanks

6 Likes

Up-voting this.

I ran into an issue recently when using 5.0.3 on a mobile VR scene. I made multiple optimization passes on my scene but just couldn’t seem to maintain frame rate. I brought RenderDoc in and found the culprit. Despite having precomputed occlusion culling active (and aggressive) there were still elements of my scene which were clearly hidden but still coming through when deployed to the device. Below is a section of the scene in question through various stages of the render as viewed through RenderDoc.

A section of pillars midway through the render, which later on are not visible at all.

Near the end of the render you can see the section of pillars is completely covered.

To add insult to injury, in editor the occlusion culling (presumably hardware) easily culled out the pillars which could be seen by freezing the rendering and looking behind the wall.

It is my understanding that software occlusion culling could have potentially saved me the headache but is no longer supported in 5. In order to get this scene working I had to resort to a lot of extra hand made culling using the precomputed visibility override volumes.

4 Likes

So, based on the feedback received from Epic (or rather, ignored), I have a strong feeling it’s not coming any time soon or not coming at all :frowning:

Hi, I have also meet this problem. Affer struggling for a long time, I found out why:
The reasons may be:

  • Nanite

  • No existsed collision.

So what you have to do is:

  1. Make sure you have build collision primitive for your mesh and have both simple and complex collision primitives (although you can set simple for complex);
  2. r.Nanite 0, even though you have turned it off in project setting; (Nanite uses another culling system rather than occlusion culling)
  3. Try to refresh your project, by restart or something similar.

Well, I have all that. Performance is still ■■■■.

Anybody found and fixes for this?

https://developer.oculus.com/blog/updates-developers-unreal-engine-5/

image

3 Likes

@gh0stfase1 Precomputed visibility works - just tried it on Unreal 5.1.1 + Quest 2 standalone + the latest MetaXR plugin V50 ( 1.82.0 ). Hooked up RenderDoc and did a capture - it’s not rendering things it’s not supposed to.

1 Like

Great news, but it’s a royal pita to use when you have large complex level (gotta bake preview lighting using CPULM just to build precomputed vis). As you can imagine rapid iteration is down the drain with precomputed vis.

1 Like

Is this using unreal’s culling or does meta provide their own culling solution via the plugin? As of 5.2 precomputed viz doesn’t exist. You can confirm this by navigating to project settings and searching for “Warn no precomputed visibility” and enabling it, and attempting to add precomputed viz to your level by including baking lighting.


The static mesh editor and material editor preview window are it’s own ‘world’, I believe with a precomputed viz unless the meshes bounds exceed a certain size (correct me if I’m wrong). That you can see NO PRECOMPUTED VISIBILITY on each preview and in the editors is a sign that it doesn’t exist.

Did you try this from the docs?

Round Robin Occlusion for VR

Round Robin Occlusion is one of the dynamic occlusion query methods to improve stereo rendering performance by alternating between one eye each frame instead of both. There is an added frame of latency to occlusion data which could result in incorrect rendering in the the periphery with the trade off being that Round Robin Occlusion saves an entire frame’s worth of queries. The trade off in savings can help most with scenes that are draw call or visibility bound.

Enable Round Robine Occlusion in your .ini config file or at runtime using the following console variable:

     vr.RoundRobinOcclusion=1

This doesn’t yield much performance gains, comparing to software occlusion culling.

So, RIP precomputed visibility too?! Wow, as if Epic tries hard to discourage VR devs from using UE5.x for standalone VR dev.

I have a 5.1.1 build which I incorporated the old Software Occlusion Culling and I think it work.
Feel free to try it and let me know.
You can compile it yourself or you can use the torrent file I provide in Release to download the binaries.

4 Likes

Amazing work! I haven’t tried it yet (gave up on UE5 after I learned about missing software occlusion culling and uninstalled everything), but is it safe to assume you will have 5.2.1 Meta fork with software occlusion culling when it is released by Meta ?

Yes I will :wink:

2 Likes

I have am having build errors trying to package from this, lots of linker issues.

Can you be more specific ? Do you mean building the Engine ?

Build fails and cites these linker issues through out the process:

PackagingResults: Error: undefined symbol: __aarch64_swp8_acq_rel
PackagingResults: Error: undefined symbol: __aarch64_ldadd4_acq_rel
PackagingResults: Error: undefined symbol: __aarch64_ldadd4_relax
PackagingResults: Error: undefined symbol: __aarch64_cas4_relax
PackagingResults: Error: undefined symbol: __aarch64_ldadd4_rel
PackagingResults: Error: undefined symbol: __aarch64_cas4_acq_rel
PackagingResults: Error: undefined symbol: __aarch64_ldadd8_acq_rel
PackagingResults: Error: undefined symbol: __aarch64_cas8_acq_rel
PackagingResults: Error: undefined symbol: __aarch64_ldset8_rel
PackagingResults: Error: undefined symbol: __aarch64_ldadd4_acq
PackagingResults: Error: undefined symbol: __aarch64_cas8_relax
PackagingResults: Error: undefined symbol: __aarch64_cas8_acq
PackagingResults: Error: undefined symbol: __aarch64_ldset8_acq
PackagingResults: Error: undefined symbol: __aarch64_ldset8_acq_rel
PackagingResults: Error: undefined symbol: __aarch64_ldadd8_relax
PackagingResults: Error: undefined symbol: __aarch64_cas8_rel
PackagingResults: Error: undefined symbol: __aarch64_ldset4_rel
PackagingResults: Error: undefined symbol: __aarch64_swp1_acq_rel
PackagingResults: Error: undefined symbol: __aarch64_cas1_acq_rel
PackagingResults: Error: undefined symbol: __aarch64_swp4_acq_rel
PackagingResults: Error: too many errors emitted, stopping now (use -error-limit=0 to see all errors)
PackagingResults: Error: linker command failed with exit code 1 (use -v to see invocation)
PackagingResults: Error: Unknown Error

I’m using ndk 21 with min sdk set to 31 and max set to 32 if that helps.

Are you compiling under Linux? Most posts on forums with similar errors point to compile problems with certain versions of gcc.

Nah, he is on Windows 100%.