Oculus Go is a new standalone VR headset. It is compatible with the same Mobile SDK, Unity, and Unreal SDKs that power Oculus applications on Samsung Gear VR, and most Gear VR apps will run unmodified on Oculus Go. This post details our recommendations for developing Oculus Go apps and details some of the new tools and technical features we've built into this device.

Gear VR Compatible

Google Play Services: Unlike the Samsung Galaxy devices that run Gear VR, Oculus Go does not ship with Google Play Services installed. You cannot rely on Google Play Services (e.g. Google Firebase, Google Cloud Messaging, etc.), or third-party libraries that depend on Google Play Services (e.g. OneSignal) when running on Oculus Go.

Unlike the Samsung Galaxy devices that run Gear VR, Oculus Go does not ship with Google Play Services installed. You cannot rely on Google Play Services (e.g. Google Firebase, Google Cloud Messaging, etc.), or third-party libraries that depend on Google Play Services (e.g. OneSignal) when running on Oculus Go. 2D Surfaces: Oculus Go does not have a 2D phone display, and therefore some app behaviors (such as push notifications, or authentication via a separate Android application) do not make sense on Oculus Go.

Oculus Go does not have a 2D phone display, and therefore some app behaviors (such as push notifications, or authentication via a separate Android application) do not make sense on Oculus Go. Camera: Oculus Go does not have a camera and cannot run applications that rely upon access to a camera.

Oculus Go does not have a camera and cannot run applications that rely upon access to a camera. HMD Touchpad: Oculus Go does not have a touchpad on the HMD. Your app should not refer to an HMD touchpad when running on Oculus Go.

Oculus Go does not have a touchpad on the HMD. Your app should not refer to an HMD touchpad when running on Oculus Go. Different Controller: The Oculus Go Controller and Gear VR Controller share the same inputs: both are 3DOF controllers with clickable trackpads and an index finger trigger. Though these two devices provide the same inputs, the physical design of each is distinct. If your app displays a visible controller, you should change the model displayed depending on whether you are running on Gear VR or Oculus Go. Alternatively, a stylized controller model that is distinct from both the Oculus Go Controller and the Gear VR Controller is acceptable.

The Oculus Go Controller and Gear VR Controller share the same inputs: both are 3DOF controllers with clickable trackpads and an index finger trigger. Though these two devices provide the same inputs, the physical design of each is distinct. If your app displays a visible controller, you should change the model displayed depending on whether you are running on Gear VR or Oculus Go. Alternatively, a stylized controller model that is distinct from both the Oculus Go Controller and the Gear VR Controller is acceptable. Recent SDK Required: Some very old Gear VR apps are still running on pre-1.0 releases of the Mobile SDK. These apps are not supported on Oculus Go.

Oculus Go is binary-compatible with Gear VR for most applications, and your existing Gear VR app can be deployed to an Oculus Go device and can usually be launched without modification. (Further below we discuss how to review and correct compatibility issues). However, there are a few areas where Oculus Go and Gear VR differ that are worth considering.

Recommended Development Environment

We recommend developing for Oculus Go and Gear VR with the following tools:

Unity 5.6.5p2 or 2017.4.1 with Oculus Utils 1.24.1 or later (required for many new features described below).

Unreal 4.18, pulled from Oculus' GitHub mirror.

For native code applications, Mobile SDK 1.14 or later.

Note that Oculus Go applications do not require “osig” files to run on retail devices. However, turning on access to adb to push application builds to an Oculus Go device requires “Developer Mode” be turned on, which in turn requires that you have created an Organization on the Oculus Developer Dashboard.

Fixed Foveated Rendering and other New Features

Oculus Go contains some unique features and improvements, including Fixed Foveated Rendering, Dynamic Throttling, and 72 Hz mode. Optimizing Oculus Go For Performance contains detailed technical discussion of these features. For lots more thoughts about using fixed foveated rendering, check out Oculus graphics engineer Rémi Palandri's OC4 talk at https://youtu.be/pjg309WSzlM?t=1671.

Here's a quick overview of the APIs involved.

Fixed Foveated Rendering

In Unity fixed foveated rendering can be enabled or disabled using the OVRManager.tiledMultiResLevel property.

OVRManager.tiledMultiResLevel = OVRManager.TiledMultiResLevel.{Off/LMSLow/LMSMedium/LMSHigh};

In Unreal, this functionality is available in the 1.21 release of the Oculus branch for 4.18, as well as in 4.19 upstream. To enable fixed foveated rendering, call:

void UOculusFunctionLibrary::SetTiledMultiresLevel(ETiledMultiResLevel level)

Native developers should call:

// 0 - off, 1 - low, 2 - medium, 3 - high

vrapi_SetPropertyInt(&m_jni.m_java, VRAPI_FOVEATION_LEVEL, {0/1/2/3})

You can check to see if fixed foveated rendering is helping your application by inspecting the total GPU utilization with the feature on or off. Note that FFR will not help applications that do not have high GPU utilization. If your utilization is low, we recommend increasing the size of the eye buffer (see below) to 1280x1280 or higher. GPU utilization is reported by the operating system once per second in logcat. The log looks like this:

11-08 18:46:58.860 1698 1762 I UtilPoller: GPU Util 0.713356 / CPU Util 0.938144 (avg 0.839895)

Code provided here is available for use under the Oculus Examples License

Dynamic Throttling

Oculus Go includes a new approach to heat and battery management called Dynamic Throttling (described in the Optimizing Oculus Go For Performance document linked above). Dynamic Throttling does not require any new API--it uses the existing CPU Level and GPU Level interface to define a minimum clock level. However, for performance debugging it is useful to turn Dynamic Throttling off so that it does not interfere with performance timing. You can do this via adb:

adb shell setprop debug.oculus.adaclocks.force 0

The system will remain off until you restart the device or turn Dynamic Throttling back on by setting the above property to 1.

If you are using Oculus Go is your primary dev kit, we recommend turning dynamic throttling (and fixed foveated rendering) off to find the correct CPU and GPU levels for Gear VR.

72 Hz Mode

Oculus Go can optionally run at 72 frames per second rather than the normal 60 frames per second for increased brightness and color clarity. In Unity, you can turn on 72 Hz mode via the displayFrequency property in OVRDisplay. You can also use OVRManager.display.displayFrequenciesAvailable to get a list of display frequencies that the device supports.

OVRManager.display.displayFrequency = 72.0f;

In Unreal, the SetDisplayFrequency Blueprint node will set the display frequency (use GetAvailableDisplayFrequencies to see what the device supports). You can also call ovrp_SetSystemDisplayFrequency() if you prefer.

For native code developers, vrapi_SetDisplayRefreshRate() can be used to set the refresh rate.

vrapi_SetDisplayRefreshRate( app->GetOvrMobile(), 72.0f );

The available refresh rates can be queried with vrapi_GetSystemPropertyInt() using VRAPI_SYS_PROP_NUM_SUPPORTED_DISPLAY_REFRESH_RATES to get the number of supported rates, and vrapi_GetSystemPropertyFloatArray() with VRAPI_SYS_PROP_SUPPORTED_DISPLAY_REFRESH_RATES to get an array of the actual rates that are supported.

Performance Tuning

As with Gear VR applications, there are a few basic settings that should be enforced for all Oculus Go applications:

Always render with Multi-View (what Unity calls “Single-Pass Stereo” rendering). In Unreal, ensure that you are using “Mobile Multi-View” and “Mobile Multi-View Direct.”

In Unity, using OVRManager, disable Enable Adaptive Resolution.

In Unity, ensure Dynamic Batching and Static Batching are both enabled in the Player Settings. Graphics Jobs should not be used.

You can use OVR Metrics Tool to render a real-time performance graph overlay in the headset. Using OVR Metrics Tool on Oculus Go requires setting some system properties (via the adb shell setprop command ) to alter the displayed information for the performance HUD. These are as follows:

debug.oculus.omms.enableGraph

debug.oculus.omms.enableGraph2

debug.oculus.omms.enableStats

debug.oculus.omms.pitch/.yaw/.distance/.scale

debug.oculus.omms.headLocked

(true|false) - show or hide the overall performance graph(true|false) - show a more detailed set of graphs for some stats.(true|false) - show or hide stats display.(number) - control the HUD position(true|false) - whether to head lock the hud or position it in space

Here are a few more system properties that can be useful for tuning performance, particularly for observing the impact of increased eye buffer resolution and fixed foveated rendering without having to rebuild an app for every test.

debug.oculus.textureWidth (number) - set the default eye buffer width. Applications must be restarted to see the effect. Default is 1024.

debug.oculus.textureHeight (number) - as above, but for default eye buffer height.

debug.oculus.foveation.level (0/1/2/3) - turn fixed foveated rendering on at the specified level (or 0 for off). Can be toggled in real time as the app is running.

By combining these commands with the utilization information found in adb logcat referenced above, you can quickly tune both eye buffer size and fixed foveated rendering level based on the GPU load. Here's an example:

First, before launching the app, we can change the default eye buffer to 1280x1280 and make sure fixed foveation is off:

adb shell debug.oculus.textureWidth 1280 adb shell debug.oculus.textureHeight 1280 adb setprop debug.oculus.foveation.level 0

Now we launch the app and scan the log for performance information.

adb logcat | grep -e UtilPoller -e VrApi

This yields:

GPU Util 0.916190 / CPU Util 0.640000 (avg 0.543814)

FPS=42,Prd=47ms,Tear=0,Early=0,Stale=39,VSnc=1,Lat=1,CPU2/GPU=2/3

This means we're running at 42 fps and we're at ~91% GPU utilization, so we are GPU-bound. Now, while the app is running, we can turn on fixed foveated rendering and see what happens:

adb setprop debug.oculus.foveation.level 1

adb logcat | grep -e UtilPoller -e VrApi

Which results in:

GPU Util 0.591578 / CPU Util 0.625000 (avg 0.506702)

FPS=60,Prd=47ms,Tear=0,Early=0,Stale=0,VSnc=1,Lat=1,CPU2/GPU=2/3

In this case, even the lowest level of fixed foveation has brought the GPU utilization down to ~60% and pushed the frame rate back up to 60. Once the FFR and eye buffer values have been tuned I can modify my application to set these values on startup.

Submitting Apps and Updates for Oculus Go

Oculus Go application submission and updates are performed through the existing Oculus Developer Dashboard for Gear VR. Pushing an update to an application will push it both to Oculus Go and Gear VR users, and the process for new app submission remains largely the same. Here are a few new things to keep in mind when submitting apps or updates: