Oculus Go Development

On 6/23/20 Oculus announced plans to sunset Oculus Go. Information about dates and alternatives can be found in the Oculus Go introduction.

Oculus Quest Development

All Oculus Quest developers MUST PASS the concept review prior to gaining publishing access to the Quest Store and additional resources. Submit a concept document for review as early in your Quest application development cycle as possible. For additional information and context, please see Submitting Your App to the Oculus Quest Store.

Fixed Foveated Rendering (FFR)

Fixed Foveated Rendering (FFR) renders the edges of your eye textures at a lower resolution than the center. The effect lowers the fidelity of the scene in the viewer’s peripheral vision, and is nearly imperceptible. This reduces the GPU load as a result of the reduction in pixel shading requirements. In addition, apps using FFR can dramatically increase the resolution of the eye texture, improving the image shown in the headset. Complex fragment shaders also benefit from this form of multi-resolution rendering.

Note that unlike some other forms of foveation technologies, Oculus Quest’s fixed foveation system is not based on eye tracking. The highest-resolution pixels are “fixed” in the center of the eye texture.

A detailed look at the benefits of using FFR can be found in our Optimizing Oculus Go for Performance blog post.

Implementing Fixed Foveated Rendering

First, if you want to check if the device supports foveated rendering. Check the system property VRAPI_SYS_PROP_FOVEATION_AVAILABLE, which will return VRAPI_TRUE if foveated rendering is supported.

Then, to use FFR, call the following to set the degree of foveation:

vrapi_SetPropertyInt( &Java, VRAPI_FOVEATION_LEVEL, level );

When calling, level can be 0, 1, 2, 3, or 4:

  • 0 disables multi-resolution
  • 1 low FFR setting
  • 2 medium FFR setting
  • 3 high FFR setting
  • 4 high top FFR setting

Dynamic Foveation

The foveation level can also be configured to be automatically adjusted based on the GPU utilization. Dynamic foveation can be enabled with:

vrapi_SetPropertyInt( &Java, VRAPI_DYNAMIC_FOVEATION_ENABLED, true );

Dynamic foveation is disabled by default. When dynamic foveation is enabled, the foveation level will be adjusted automatically with a maximum level set to VRAPI_FOVEATION_LEVEL. Foveation levels 3 (high) and level 4 (high top) are treated as the same level under dynamic foveation. Which of these two levels is chosen coincides with the VRAPI_FOVEATION_LEVEL selection. For example, if VRAPI_FOVEATION_LEVEL is set to level 4, dynamic foveation will vary between levels 0, 1, 2, and 4 exclusively.

Because dynamic foveation uses GPU utilization to increase or decrease foveation level, it’s fairly reactive and the level should increase before a stale frame is created in comparison to a fixed FFR level, but if increased stale frames are noticed in specific levels, dynamic FFR can be enabled and disabled in those areas. Use of dynamic FFR is highly recommended.

Foveation Example Images

In the following images, the resolution in the center white areas is native: every pixel of the texture will be computed independently by the GPU. However, in the red areas, only 1/2 of the pixels will be calculated, 1/4 for the green areas, 1/8 for the blue areas, and 1/16 for the magenta tiles. The missing pixels will be interpolated from the calculated pixels at resolve time, when the GPU stores the result of its computation in general memory.

Low FFR

Medium FFR

High FFR

High Top FFR

You may choose to change the degree of foveation based on the scene elements. Apps or scenes with high pixel shader costs will see the most benefit from using FFR. Apps with very simple shaders may see a net performance loss from the overhead of using FFR. Proper implementation of FFR requires testing and tuning to balance visual quality and GPU performance.

Tips and Best Practices

Many developers simply use the high FFR setting for their entire app as a general solution for performance, which some have found to have a very noticeable impact on visuals. Here are some tips and best practices on better tuning the FFR settings in-game:

  • FFR levels can be changed on a per-frame basis and should be changed according to the content being displayed. In cases where the player may need to look to the sides of the field of view more often, if high frequency content such as text is introduced, or if performance requirements change, the FFR level should be changed to match the situation. Starting a new level, opening/closing menus, and entering new map areas are generally good points to consider changing the FFR setting. However, avoid changing FFR levels frequently within the same scene without another transition as the jump between FFR levels can be fairly noticeable.
    • A simple, effective example would be to turn off FFR on menu screens, where there is performance headroom to spare and a lot of text elements, and then turning it on after loading into the game where the performance is needed.
    • Another example would be to set FFR to medium or low on an outdoor scene, changing to high when entering a darker cave or tunnel level, and then switching back to medium when changing to an outdoor level again.
  • Foveation is more apparent and noticeable in bright/high contrast scenes, and with higher frequency content such as text. In darker/low contrast scenes, the high foveation setting may result in reasonable visual quality, while that may not be the case in a brighter/higher contrast scene. This can play into what foveation level can be used for certain scenes in a game, and should be used in conjunction with the ability to change FFR levels per-frame. Medium should be a suitable FFR level in most cases, but low is a good option if there is performance to spare. High and high top should be reserved for cases where the extra performance is really needed.
  • The system property debug.oculus.foveation.level is a system-wide FFR setting override that can be used to quickly test different FFR settings without changing/reinstalling/restarting the app, with 0 = Off, 1 = Low, 2 = Medium, 3 = High, 4 = High Top (for example, adb shell setprop debug.oculus.foveation.level 2 will set the FFR level to medium).
  • Use the VrApi logcat outputs to determine suitable FFR levels. VrApi generates performance information in logcat every second, including FFR level, GPU rendering times, and average FPS. The sample log FPS=72,Prd=45ms,Tear=0,Early=67,Stale=0,VSnc=1,Lat=1,Fov=3,CPU4/GPU=2/2,1651/414MHz,OC=FF,TA=0/0/0,SP=N/N/N,Mem=1017MHz,Free=1576MB,PSM=0,PLS=0,Temp=27.0C/0.0C,TW=2.25ms,App=5.51ms,GD=0.77ms shows an app running at 72 fps (FPS=72), with the app’s GPU rendering time at 5.51ms (App=5.51ms), and FFR on high (Fov=3). Regardless of visuals, in this case there is more than enough room to turn the FFR level down for a general improvement in the visual quality.