Forum Discussion
CodingJar
10 years agoProtege
5.3.0f4 Profiling - Slow - OculusWaitForGPU
Hello!
I'm new to Gear VR development and we're trying to push our game out before Christmas so all the boys and girls have more fun games to play when they unwrap their presents. However, we want the game to be really high quality and that means hitting 60fps at all times. What I'm noticing is that we're constantly hitting 30fps, not 60fps according to the Unity 5.3.0f4 profiler. Digging into the issue reveals that it's waiting for OculusWaitForGPU.
Now before you jump the gun and say "that's your rendering performance!" That was also what I first looked at, but no matter what I do, I can't seem to get it back to 60fps. Here's a screenshot of what I'm seeing before I start explaining what I've gone through:
Profiler.jpg
Now most other posts say it's because you're rendering too much and waiting for the GPU thread to finish before continuing, but the wait time is above 19ms, with a whole frame being 16.6ms that means we've waited an entire frame! So am I rendering too much? Well, if I look at the GPU chart (just below the CPU one) it appears my Camera.Render time is 0.5ms! Here is the picture to show I'm not making this up:
GPU.jpg
Now this is with all of the 'optimizations' as suggested by Oculus (multithreaded rendering, GPU Skinning, static and dynamic batching, etc.) I've also tried IL2CPP and .NET, no difference.
Now I'm a pretty experienced Unity dev (5+ years, shipped titles, etc.) so I'm aware that not all of those optimizations apply to every game... and my hunch was that the multi-threaded rendering with profiling is enforcing a frame lock-step, killing the performance. So I tried disabled multi-threaded rendering (and dynamic batching, since that sometimes can hurt performance if you're drawing large meshes). The results are fairly different:
Single-Threaded.jpg
This seems to indicate it's the submission of the geometry/draw calls rather than the rendering that is slowing the application down, and this time the OculusWaitForGPU is never over 16.6ms. Is this the correct interpretation? Why am I not seeing the geo/draw submission time in multi-threaded rendering? Isn't multi-threaded rendering supposed to help with this by overlapping the update/submission with rendering, and how come I can't see the advantage?
And the big question: How do I get my performance back up to 60fps. If those GPU times are correct, it seems like it's spending almost no time rendering, but all of its time getting ready to render?
Thanks!
I'm new to Gear VR development and we're trying to push our game out before Christmas so all the boys and girls have more fun games to play when they unwrap their presents. However, we want the game to be really high quality and that means hitting 60fps at all times. What I'm noticing is that we're constantly hitting 30fps, not 60fps according to the Unity 5.3.0f4 profiler. Digging into the issue reveals that it's waiting for OculusWaitForGPU.
Now before you jump the gun and say "that's your rendering performance!" That was also what I first looked at, but no matter what I do, I can't seem to get it back to 60fps. Here's a screenshot of what I'm seeing before I start explaining what I've gone through:
Profiler.jpg
Now most other posts say it's because you're rendering too much and waiting for the GPU thread to finish before continuing, but the wait time is above 19ms, with a whole frame being 16.6ms that means we've waited an entire frame! So am I rendering too much? Well, if I look at the GPU chart (just below the CPU one) it appears my Camera.Render time is 0.5ms! Here is the picture to show I'm not making this up:
GPU.jpg
Now this is with all of the 'optimizations' as suggested by Oculus (multithreaded rendering, GPU Skinning, static and dynamic batching, etc.) I've also tried IL2CPP and .NET, no difference.
Now I'm a pretty experienced Unity dev (5+ years, shipped titles, etc.) so I'm aware that not all of those optimizations apply to every game... and my hunch was that the multi-threaded rendering with profiling is enforcing a frame lock-step, killing the performance. So I tried disabled multi-threaded rendering (and dynamic batching, since that sometimes can hurt performance if you're drawing large meshes). The results are fairly different:
Single-Threaded.jpg
This seems to indicate it's the submission of the geometry/draw calls rather than the rendering that is slowing the application down, and this time the OculusWaitForGPU is never over 16.6ms. Is this the correct interpretation? Why am I not seeing the geo/draw submission time in multi-threaded rendering? Isn't multi-threaded rendering supposed to help with this by overlapping the update/submission with rendering, and how come I can't see the advantage?
And the big question: How do I get my performance back up to 60fps. If those GPU times are correct, it seems like it's spending almost no time rendering, but all of its time getting ready to render?
Thanks!
11 Replies
Replies have been turned off for this discussion
- vrdavebOculus StaffThose profiler graphs appear to be captured on the PC. Unfortunately, Unity's GPU profiler doesn't work yet with Gear VR. I see you have >200 batches, >245k triangles, and >190 vertices. We typically recommend ~100 total draw calls, and no more than 100k triangles or vertices. There is some wiggle room there, but it gets hard to hit 60fps above those values.
To reduce draw calls, I assume you've already enabled dynamic and static batching and that you're using the same materials on as many objects as possible. You may be able to consolidate materials further by using texture atlasing. There are Asset Store packages such as Pro Draw Call Optimizer that can help here (see https://www.assetstore.unity3d.com/en/#!/content/16538).
To reduce geometry, I assume you've already enabled culling and simplified your meshes and baked detail into textures (see https://www.assetstore.unity3d.com/en/#!/content/43658, http://www.katsbits.com/tutorials/blend ... l-maps.php). Consider generating even-lower LOD versions and using Unity's LOD Groups to swap them in when the full meshes aren't needed (http://docs.unity3d.com/Manual/class-LODGroup.html). - CodingJarProtegeHello,
I'm back! Just submitted our app for approval! Turns out 5.3.0f4 isn't quite ready for VR, "downgrading" to 5.2.3p3 was the solution to solve the multi-threaded issue. The graphs were actually not taken from the PC, you can enable them in the Unity Editor Profiler on your Android build (they don't seem to display by default). However, it looks like they may have been incorrect on 5.3.0f4, but show a much better picture on 5.2.3p3. To summarize, transparent particle effects are killer. Any particle effect that is set to Pre-Warm will absolutely kill your performance.
We managed to make it to 60fps the majority of the time by object pooling, using a package optimized for mobile blob shadow projectors, reducing as much transparent particles as possible, and using a custom terrain mesh.
We occassionally go from 60fps to 30fps whenever there are massive amounts of particles on the screen -- it's a real shame there's no in between frame rates. Miss 60hz by 1ms and all of the sudden you're at 30hz. Also, if you play the game for long enough the phone will overheat. In the new Unity 5 SDKs, there's now way to enforce 30hz TimeWarp which is a real shame as I think our game might be able to get away with it to avoid over-heating issues.
You can see screenshots from our game at http://ElementalistX.com
Cheers! - nosys70Expert Protegeyou could also improve your website by not displaying huge pictures (2560x1440) in tiny size (458x257)
- vrdavebOculus Staff
"CodingJar" wrote:
Turns out 5.3.0f4 isn't quite ready for VR, "downgrading" to 5.2.3p3 was the solution to solve the multi-threaded issue.
If that works for you, then great. 5.3.1f1 also appears to contain the fix. We are still testing that version and we'll update the recommended version when we confirm nothing else has broken."CodingJar" wrote:
In the new Unity 5 SDKs, there's now way to enforce 30hz TimeWarp
There is still a way to do this, but it's fragile and may not work in future releases. See SDKExamples' TimeWarp30HzSample script. When we deprecate OVRPlugin's OVR_TW_SetMinimumVsyncs, we will update the SDKExamples to do it the new way. - CodingJarProtegeWhen I import your SDK it tells me that it's compatible with Unity 4.x only. Unity 5.x uses a different plug-in that I was worried would conflict with the library provided by your SDK. To clarify, I can import your SDK / libraries, ignore the warning that it's only compatible with Unity 4.x and achieve a 30hz TimeWarp without it affecting Unity 5.x's built-in functionality?
I tried manually exposing the "frequency" key from your Unity 5.x Utilities, but it's read-only and throws an exception when written to. - vrdavebOculus StaffWe have two separate (but similar) integrations for Unity 4 and Unity 5. In Unity 4, you need the package even for basic VR support. In Unity 5, VR support is built-in and our downloadable package is optional (but you need to use it to submit apps to our store). Please follow this doc to get set up properly in Unity 5: https://developer.oculus.com/documentat ... ity-intro/
- CodingJarProtegeDave,
Unity 4.x needs libraries provided by Oculus. Unity 5.x has libraries provided by Unity with a small plug-in to augment functionality provided by Oculus. In the Unity 5.x integration I do not see any functionality that allows us to set TimeWarp. Are you certain it's in there? Can you point me to the function? There are no OVR_TW functions anymore. This leads me to believe that you cannot use this functionality in Unity 5.x, only in Unity 4.x. - vrdavebOculus StaffFirst, you need to be using Unity 5's built-in VR support by enabling the "Virtual Reality Supported" player setting. Second, you need to import the Oculus Utilities for Unity 5 (see https://developer.oculus.com/downloads/ ... r_Unity_5/). Third, to get 30Hz TimeWarp support, you need to write code similar to TimeWarp30HzSample.cs in SDKExamples, which you can download from https://developer.oculus.com/downloads/ ... _Examples/.
- vrdavebOculus StaffThe OVR_TW_SetMinimumVsyncs function is exported by OVRPlugin.dll, which is a DLL inside of Unity 5. TimeWarp30HzSample.cs imports and uses this function to render at 30Hz. However, OVR_TW_SetMinimumVsyncs is a temporary solution and it will go away in the future. When it goes away, you will have to update to a similar function in OVRDisplay, after we add it.
- CodingJarProtegeSo I've managed to find the funcitonality. Note that OculusPlugin is renamed internally to OVRPlugin. Here is the code in case anyone else tries to achieve this in Unity 5.3. Unfortunately it doesn't seem to completely solve our thermal issues as we still heat up after around 20mins of gameplay, even at 30fps. Is this a typical issue with games?
using UnityEngine;
using System.Runtime.InteropServices;
/// <summary>
/// Helper class to modify the internal Oculus TimeWarp values.
/// </summary>
public class OVRTimeWarp : MonoBehaviour
{
public enum VsyncMode
{
VSYNC_60FPS = 1,
VSYNC_30FPS = 2,
VSYNC_20FPS = 3
}
#pragma warning disable 414
[SerializeField]
VsyncMode targetFrameRate = VsyncMode.VSYNC_30FPS;
#pragma warning restore
#if (UNITY_ANDROID && !UNITY_EDITOR)
[DllImport("OVRPlugin")]
// Support to fix 60/30/20 FPS frame rate for consistency or power savings
private static extern void OVR_TW_SetMinimumVsyncs( VsyncMode mode );
#endif
/// <summary>
/// Start modifying the TimeWarp
/// </summary>
void Start()
{
if (!OVRManager.isHmdPresent)
{
enabled = false;
return;
}
#if (UNITY_ANDROID && !UNITY_EDITOR)
Debug.LogWarning( "Setting TimeWarp Rate to: " + targetFrameRate );
OVR_TW_SetMinimumVsyncs( targetFrameRate );
#endif
}
}
Quick Links
- Horizon Developer Support
- Quest User Forums
- Troubleshooting Forum for problems with a game or app
- Quest Support for problems with your device
Other Meta Support
Related Content
- 2 years ago
- 3 years ago
- 5 months ago