Name

    QCOM_framebuffer_foveated

Name Strings

    GL_QCOM_framebuffer_foveated

Contributors

    Skyler Saleh
    Maurice Ribble
    Tate Hornbeck
    Jonathan Wicks
    Robert VanReenen

Contact

    Jeff Leger - jleger 'at' qti.qualcomm.com

Status

    Complete

Version

    Last Modified Date: May 10, 2017
    Revision: #11

Number

    OpenGL ES Extension #273

Dependencies

    OpenGL ES 2.0 is required.  This extension is written against OpenGL ES 3.2.

Overview

    Foveated rendering is a technique that aims to reduce fragment processing
    workload and bandwidth by reducing the average resolution of a framebuffer.
    Perceived image quality is kept high by leaving the focal point of
    rendering at full resolution.

    It exists in two major forms:

        - Static foveated(lens matched) rendering: where the gaze point is
        fixed with a large fovea region and designed to match up with the lens
        characteristics.
        - Eye-tracked foveated rendering: where the gaze point is continuously
        tracked by a sensor to allow a smaller fovea region (further reducing
        average resolution)

    Traditionally foveated rendering involves breaking a framebuffer's area
    into smaller regions such as bins, tiles, viewports, or layers which are
    rendered to individually. Each of these regions has the geometry projected
    or scaled differently so that the net resolution of these layers is less
    than the original framebuffer's resolution. When these regions are mapped
    back to the original framebuffer, they create a rendered result with
    decreased quality as pixels get further from the focal point.

    Foveated rendering is currently achieved by large modifications to an
    applications render pipelines to manually implement the required geometry
    amplifications, blits, and projection changes.  This presents a large
    implementation cost to an application developer and is generally
    inefficient as it can not make use of a platforms unique hardware features
    or optimized software paths. This extension aims to address these problems
    by exposing foveated rendering in an explicit and vendor neutral way, and by
    providing an interface with minimal changes to how an application specifies
    its framebuffer.

New Tokens

    Allowed in the config input in FramebufferFoveationConfigQCOM:

        FOVEATION_ENABLE_BIT_QCOM                    0x1
        FOVEATION_SCALED_BIN_METHOD_BIT_QCOM         0x2

New Procedures and Functions

    void FramebufferFoveationConfigQCOM(uint fbo,
                                       uint numLayers,
                                       uint focalPointsPerLayer,
                                       uint requestedFeatures,
                                       uint *providedFeatures);

    void FramebufferFoveationParametersQCOM(uint fbo,
                                           uint layer,
                                           uint focalPoint,
                                           float focalX,
                                           float focalY,
                                           float gainX,
                                           float gainY,
                                           float foveaArea);

Additions to Chapter 9 of the OpenGL ES 3.2 Specification

    The command

    void FramebufferFoveationConfigQCOM( uint fbo, uint numLayers,
    uint focalPointsPerLayer, uint requestedFeatures, uint *providedFeatures);

    is used to configure foveated rendering for the framebuffer object 'fbo'
    and to instruct the implementation to allocate any additional
    intermediate resources needed for foveated rendering.

    In order to enable foveation, this call must be issued prior to any
    operation which causes data to be written to a framebuffer attachment.
    Once this call is made for a framebuffer object, the fbo will remain a
    "foveated fbo". The following scenarios are unsupported conditions:

        1. Rendering to a non foveated fbo, then calling
           FramebufferFoveationConfigQCOM results in current framebuffer content
           becoming undefined.

        2. Rendering to a foveated fbo then switching attachments results in an
           error.

    Each layer of a foveated framebuffer, the max of which is specified by
    'numLayers', can have multiple focal points as controlled by
    'focalPointsPerLayer'. This enables applications that make use of double
    wide rendering to utilize foveated rendering and also allows more complex
    falloff characteristics to be modeled with multiple overlapping focal
    points. There are limitations to the number of focal points that an
    implementation can support with different enabled features or framebuffer
    formats. When an implementation can not support having as many focal points
    per layer as was specified in this function, it will fail with the error
    INVALID_VALUE. It is recommended that an application utilize as
    few focal points per layer as possible.

    The 'requestedFeatures' bitfield is used to specify which features an
    application would like to use.

    An explanation of each of the features is below:

        FOVEATION_ENABLE_BIT_QCOM: Is used to enable foveated rendering, if
        this bit is not specified foveated rendering will not be used.

        FOVEATION_SCALED_BIN_METHOD_BIT_QCOM: Requests that the implementation
        perform foveated rendering by dividing the framebuffer into a grid of
        subregions. Each subregions will be greater than or equal to one pixel
        and less than or equal to the full framebuffer. Then rendering the geometry
        to each of these regions with a different projection or scale. Then, finally
        upscaling the subregion to the native full resolution framebuffer.
        Quality in the scaled bin method is defined as a minimum pixel density
        which is the ratio of the resolution rendered compared to the native
        framebuffer.

    In the future it is expected that more features will be added, without
    breaking backwards compatibility.

    'providedFeatures' is a pointer to a uint that will be set to a new bitfield
    that tells the application which features the implementation provided for the
    current foveation configuration, in the same format as used in the 'requested
    Features' bitfield. This may include more or fewer features than the application
    requested.  The FOVEATION_ENABLE_BIT_QCOM will not be included if the
    implementation has to fallback to non-foveated rendering.

    If an application tries to make use of a feature that is not included in the
    'providedFeatures' bitfield, the results of the operation are implementation
    defined, but should not yield application termination.

    If this command is called with 'requestedFeatures' equal to zero, then the value
    of 'providedFeatures' will have FOVEATION_ENABLE_BIT_QCOM unset, and the other
    bits will be set or unset to indicate which foveation features are supported
    by the implementation.

    The command

    void FramebufferFoveationParametersQCOM(uint fbo,uint layer, uint focalPoint,
    float focalX, float focalY, float gainX, float gainY, float foveaArea);

    is used to control the falloff of the foveated rendering of 'focalPoint'
    for layer  'layer' in the framebuffer object 'fbo'. Multiple focal points
    per layer are provided to enable foveated rendering when different regions
    of a framebuffer represent different views, such as with double wide
    rendering. Values of 0 to the framebuffers focalPointsPerLayer-1 are valid
    for the 'focalPoint' input and specify which focal point's data to update
    for the layer.

    'focalX' and 'focalY' is used to specify the x and y coordinate
    of the focal point of the foveated framebuffer in normalized device
    coordinates. 'gainX' and 'gainY' are used to control how quickly the
    quality falls off as you get further away from the focal point in each
    axis. The larger these values are the faster the quality degrades.
    'foveaArea' is used to control the minimum size of the fovea region, the
    area before the quality starts to fall off. These parameters should be
    modified to match the lens characteristics.

    For the scaled bin method, these parameters define the minimum pixel
    density allowed for a given focal point at the location (px,py) on a
    framebuffer layer in NDC as:

    min_pixel_density=0.;
    for(int i=0;i<focalPointsPerLayer;++i){
        focal_point_density = 1./max((focalX[i]-px)^2*gainX[i]^2+
                            (focalY[i]-py)^2*gainY[i]^2-foveaArea[i],1.);
        min_pixel_density=max(min_pixel_density,focal_point_density);
    }

    While this function is continuous, it is worth noting that an
    implementation is allowed to decimate to a fixed number of supported
    quality levels, and it is allowed to group pixels into larger regions of
    constant quality level, as long as the implementation at least provides
    the quality level given in the above equation.

    Future supported foveation methods could have different definitions of
    quality.

    The default values for each of the focal points in a layer is:

    focalX=focalY=0;
    gainX=gainY=0;
    foveaArea=0;

    Which requires the entire framebuffer to be rendered at full quality.

    By specifying these constraints an application can fully constrain its
    render quality while leaving the implementation enough flexibility to
    render efficiently.

Errors

    OUT_OF_MEMORY is generated by FramebufferFoveationConfigQCOM if an
    implementation runs out of memory when trying to reserve the needed
    additional resources for the foveated framebuffer.

    INVALID_VALUE is generated by FramebufferFoveationConfigQCOM if 'fbo' is
    not a valid framebuffer.

    INVALID_VALUE is generated by FramebufferFoveationConfigQCOM if 'numLayers'
    is greater than GL_MAX_ARRAY_TEXTURE_LAYERS - 1.

    INVALID_VALUE is generated by FramebufferFoveationConfigQCOM if
    'numFocalPoints' is greater than implementation can support.

    INVALID_OPERATION is generated by FramebufferFoveationConfigQCOM if it is
    called for an fbo that has already been cofigured for foveated rendering.

    INVALID_VALUE is generated by FramebufferFoveationParametersQCOM if 'fbo'
    is not a valid framebuffer.

    INVALID_OPERATION is generated by FramebufferFoveationParametersQCOM if
    'fbo' has not been configured for foveated rendering.

    INVALID_VALUE is generated by FramebufferFoveationParametersQCOM if
    'layer' is greater than or equal to the numLayers that the fbo was
    previously configured for in FramebufferFoveationConfigQCOM.

    INVALID_VALUE is generated by FramebufferFoveationParametersQCOM if
    'numFocalPoints' is greater than implementation can support.

    INVALID_OPERATION is generated by any API call which causes a framebuffer
    attachment to be written to if the framebuffer attachments have changed for
    a foveated fbo.

    INVALID_OPERATION is generated if a rendering command is issued and the
    current bound program uses tessellation or geometry shaders.

Issues

    1. Are layered framebuffers supported?

    Layered framebuffers are supported to enable stereoscopic foveated
    rendering which is a main use case of this extension. When a layered
    framebuffer is used each layer has its own set of foveation parameters.

    2. How is foveation performed?

    How foveated rendering is performed to the framebuffer is implementation
    defined. However, if 'FOVEATION_SCALED_BIN_METHOD_BIT_QCOM' is set the
    implementation must perform foveation by dividing the framebuffer into a
    grid of subregions. Then rendering the geometry to each of these regions
    with a different projection or scale. And finally upscaling the subregion
    to the native full resolution framebuffer.

    When that bit is not set the implementation can use any algorithm it
    wants for foveated rendering as long as it meets the application
    requested features.

    3. How are MRTs handled?

    Every framebuffer attachment uses the same quality in a given region.

    4. How does gl_FragCoord work?

    When using the scaled bin method, gl_FragCoord will be scaled to match
    the relative location in a foveated framebuffer. This means the absolute
    value of gl_FragCoord will not be correct in lower resolution areas,
    but the value relative to the full resolution will be consistent.

    5. How is depth handled?

    Depth surfaces can be used during foveated rendering, but the contents
    of the depth buffer will not be resolved out. The implementation can
    do an implicit discard of the depth buffer. The reasoning here is that
    the upsample of depth during resolve would produce irrelevant results.

    6. How does unresolving from a foveated framebuffer work?

    Loading from a foveated framebuffer is undefined, so the app must be
    sure not to trigger mid frame flushes. In the dynamic foveation case
    the focal point can move constantly. If a region A of a frame 0 was
    rendered at a lower quality because the focal point was far away,
    then the focal point moved to cover region A during frame 1, the
    unresolve could not reconstruct the full quality region A. The
    app must be careful to fully clear the surface and remove mid frame
    flushes to prevent unresolves.

Examples:

    (1) Initialize a foveated framebuffer

        // Allocate and initialize a regular framebuffer and attachments
        GLuint fbo = createFramebufferAndAttachments();
        GLuint providedFeatures;
        glFramebufferFoveationConfigQCOM(fbo,1,1, GL_FOVEATION_ENABLE_BIT_QCOM, &providedFeatures);
        if(!(providedFeatures & GL_FOVEATION_ENABLE_BIT_QCOM)) {
            // Failed to enable foveation
        }

    (2) Setup static foveated rendering

        // Insert code from #1
        GLfloat focalX=0.f, focalY=0.f;  // Setup focal point at the center of screen
        GLfloat gainX=4.f, gainY=4.f;  // Increase these for stronger foveation
        glFramebufferFoveationParametersQCOM(fbo, 0, 0, focalX, focalY, gainX, gainY, 0.f);

    (3) Change eye position for eye tracked foveated rendering

        // Code called whenever the eye position changes
        // It is best to position this call both before rendering anything to
        //   an fbo and right before Flush or changing FBO since some
        //   some implementations can apply this state late by patching command
        //   buffers.
        glFramebufferFoveationParametersQCOM(fbo, 0, 0, focalX, focalY, gainX, gainY, 0.f);

    (4) Setting parameters for a multiview stereo framebuffer

        //focalPointsPerLayer should be 1
        float focalX1=0.f,focalY1=0.f;  // Gaze of left eye
        float focalX2=0.f,focalY2=0.f;  // Gaze of right eye
        float gain_x=10.f,gain_y=10.f;  // Strong foveation
        glFramebufferFoveationParametersQCOM(fbo, 0, 0, focalX1, focalY1,gainX, gainY, 0.f);
        glFramebufferFoveationParametersQCOM(fbo, 1, 0, focalX2, focalY2,gainX, gainY, 0.f);

    (5) Setting parameters for a double wide stereo framebuffer

        //focalPointsPerLayer should be 2
        float focalX1=0.f,focalY1=0.f;  // Gaze of left eye
        float focalX2=0.f,focalY2=0.f;  // Gaze of right eye
        float gainX=10.f,gainY=10.f;
        glFramebufferFoveationParametersQCOM(fbo, 0, 0, focalX1*0.5f-0.5f, focalY1, gainX*2.f ,gainY, 0.f);
        glFramebufferFoveationParametersQCOM(fbo, 0, 1, focalX2*0.5f+0.5f, focalY2, gainX*2.f ,gainY, 0.f);


Revision History

    Rev.    Date     Author    Changes
    ----  --------  --------  ----------------------------------------------
     1    05/19/16  ssaleh    Initial draft.
     2    05/27/16  ssaleh    Made the extension much more explicit.
     3    07/08/16  ssaleh    Further refinements.
     4    08/11/16  ssaleh    Specified bitfield values
     5    08/19/16  ssaleh    Added support for double wide rendering
     6    08/24/16  mribble   Name changes and cleanup
     7    08/24/16  ssaleh    Add examples
     8    10/14/16  tateh     Clarify gl_FragCoord
     9    01/04/17  tateh     Update entry points and cleanup
    10    02/17/17  jleger    Convert from EXT to QCOM extension.
    11    05/10/17  tateh     Minor cleanup
