Question about Culling and VR

I read in a presentation from the devs of robo recall unplugged that Occlusion Queries and precomputed visibility do not work together.

Does anyone know if it would be a problem to enable Round Robin Occlusion Queries in project settings, as well as Precompute Visibility (in World settings)? This is for a VR project on Oculus Quest.

Hey did you by any chance find any more info on this question since then?
Any info is appreciated as I’m looking into the same thing.


in addition to hardware occlusion queries (which is enabled by default) and precomputed visibility, we decided to also add software occlusion queries to our architecture (walls/floors/big meshes) to force them to work as an occluder as we had the feeling that hardware occlusion alone didn’t do the job perfectly on mobile (vulkan). Enabling these software occlusion on several meshes produced an instant drop in draw calls when testing it in the editor (we use vulkan preview).

Here’s information about the software occlusion and how to enable it per mesh: Software Occlusion Queries for Mobile | Unreal Engine Documentation

We also reduced draw calls a lot by combining meshes in the room that have the same material but adding the software occlusion seemed to help as well. There may be a CPU cost for using software occlusion but we didn’t really noticed it. If you’re using mobile VR, I would surely recommend using Multi-view in project settings reducing the load on CPU and moving it over to GPU. This way we managed to allow more draw calls without paying the (CPU) cost of it.

For now, we did not enable Round Robin Occlusion as we currently have no real performance issues anymore and we couldn’t find any decent documentation on when to use this type of occlusion.

I hope this helps.

1 Like

Fantastic! Thanks for the pointers!

Can you tell me why you chose Vulkan over OpenGL ES3.1 for performance reasons?

I have Mobile Multiview, Round robin & Instanced stereo enabled.
With Vulkan/ES3.1 enabled, I have 50% more draw calls listed as opposed to SM5.

I’m about to test out software occlusion draw call reduction with Vulkan vs ES3.1 and see if there’s any difference in the end draw call count for some reason.
Without the wiki listing these answers openly, I seemingly have to go with a test and analyze stats approach.

You’re welcome.

We use Vulkan mainly because it allows for more draw calls (objects/materials) in the scene and overall performance is better. It’s a more modern graphics API, compared to ES 3.1 and is fully supported by Oculus Quest.

Please be aware that if you enable Vulkan and multi-view, your default SM5 preview renderer will emitt black spots in the editor. You should enable Forward Shading to solve that issue (or turn off multi-view which I do not recommend). Even though documentation is confusing about FS, many recommend enabling forward shading, even for mobile, as it should provide better performance.

I would not recommend enabling instanced stereo for mobile since it is a feature used for desktop VR. You could say that mobile multi-view is the counterpart of instance stereo on mobile. So, I think enabling both could lead to possible issues (or perhaps the system will disable stereo automatically).

By using the software occlusion (and enabling it on a per-mesh basis), we managed to get an almost equal amount of draw calls in SM5, compared to Vulkan (whereas before, the latter would be much higher). However, it could also be that the ES3.1 and Vulkan previewers in the editor are not reliable in terms of the amount of draw calls they calculate. I suggest to aslo test in the headset. I think the OVR metrics tool also has a stat for draw calls.

Please indicate as answered and rate, if you think my answer meets your question.

Just to expand on my findings based on your suggestions as It might help others.

It seems like a subset of the View Frustrum culling works on Mobile devices i.e. objects outside the view frustrum are culled. However, the objects within the view frustrum do not occlude objects behind them. This only works on non-mobile devices / render modes.

This can be verified with stat initviews where we can compare the counter values for “Visible static mesh elements” and “Occluded primitives” and the occluded primites being zero in the mobile render view modes as it isn’t supported due to performance reasons.
Additionally, with r.VisualizeOccludedPrimitives 1, we can visualize the occluded objects as they are only highlighted in the non-mobile rendering modes.

That’s where the Mobile Software Occlusion comes in as you rightly suggested and enabling it performs a more cost efficient occlusion culling within the View frustrum.

Another finding, Mobile software occlusion seems to work only for meshes which have all material ids’ using certain material blend modes i.e. Opaque. Even if a single material id has a blend mode such as masked/transparent, it prevents the mesh from occluding anything behind it. It took me a while to narrow it down to this. Hopefully saves somebody some time.

Here’s another link to a page with profiling commands usable for similar analysis.

Thanks again for helping me figuring this out. Appreciate it!
I’ve upvoted your answers/comments but I believe only you can mark it answered as you created the question.

Hi Ramesh,

thanks a lot for your addition.

It explains why software occlusion is essential in having less draw calls as objects are not culled within the view frustrum. I still think it’s weird though that it doesn’t work on mobile since resources are more scarce on mobile. Also, it would be great if the software occlusion would caluculate by itself which objects should be occluded, rather than having to indicate this on a per-mesh basis. Perhaps the CPU cost would be too high.

At least we now have a solution and a proper explanation to how to solve this issue :slight_smile: