blob: ed17d9e16166743ea15006678df5cef63848de86 [file] [log] [blame]
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 a 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
// a 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