blob: cf7c6bcdb2aea1f06bc3237dc7a668fa50aae713 [file] [log] [blame]
Name
IMG_framebuffer_downsample
Name Strings
GL_IMG_framebuffer_downsample
Contributors
Tobias Hector, Imagination Technologies (tobias.hector 'at' imgtec.com)
Contact
Tobias Hector (tobias.hector 'at' imgtec.com)
Status
Complete
Version
Last Modified Date: August 20, 2015
Revision: 11
Number
OpenGL ES Extension #255
Dependencies
OpenGL ES 2.0 or OES_framebuffer_object are required.
This extension is written against the OpenGL ES 3.0.4 Specification
(August 27, 2014).
This extension has interactions with GL_EXT_multisampled_render_to_texture.
This extension has interactions with OpenGL ES 3.1.
This extension has interactions with GL_EXT_color_buffer_float.
This extension has interactions with GL_EXT_color_buffer_half_float.
Overview
This extension introduces the ability to attach color buffers to a
framebuffer that are at a lower resolution than the framebuffer itself, with
the GPU automatically downsampling the color attachment to fit.
This can be useful for various post-process rendering techniques where it is
desirable to generate downsampled images in an efficient manner, or for a
lower resolution post-process technique.
This extension exposes at least a 2 x 2 downscale. Other downsampling modes
may be exposed on the system and this can be queried.
IP Status
No known IP claims.
New Procedures and Functions
void FramebufferTexture2DDownsampleIMG(
enum target, enum attachment,
enum textarget, uint texture,
int level, int xscale, int yscale);
void FramebufferTextureLayerDownsampleIMG(
enum target, enum attachment,
uint texture, int level,
int layer, int xscale, int yscale);
New Tokens
Returned by CheckFramebufferStatus:
FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG 0x913C
Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv,
GetInteger64v, and GetInternalFormativ:
NUM_DOWNSAMPLE_SCALES_IMG 0x913D
Accepted by the <target> parameter of GetIntegerv, GetInteger64v,
GetIntegeri_v, GetInteger64i_v and GetInternalFormativ:
DOWNSAMPLE_SCALES_IMG 0x913E
Accepted by the <pname> parameter of GetFramebufferAttachmentParameteriv:
FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG 0x913F
Additions to Chapter 4 of the OpenGL ES 3.0 Specification:
Modify figure 4.1, "Per-Fragment Operations.", to add an additional box
"Downscaling" after "Additional Multisample Fragment Operations".
Add a new section 4.1.11, "Downscaling":
If no multisampling was performed, and downscaling is enabled, fragment
outputs may be optionally downscaled in a similar way to how multiple
samples are resolved. If the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_-
SCALE_IMG is not {1,1}, fragment values are written to an intermediate
buffer. After all other fragment operations have completed, they are
then combined to a produce a single color value, and that value is
written into the corresponding color buffer selected by DrawBuffers. An
implementation may defer the writing of color buffers until a later
time, but the state of the framebuffer must behave as if the color
buffers were updated as each fragment is processed. The method of
combination is not specified. If the framebuffer contains sRGB values,
then it is recommended that an average of samples is computed in a
linearized space, as for blending (see section 4.1.7). Otherwise, a
simple average computed independently for each color component is
recommended.
Add the following to Section 4.4.2 "Attaching Images to Framebuffer Objects"
after the paragraph describing FramebufferTexture2D:
The command
void FramebufferTexture2DDownsampleIMG(
enum target, enum attachment,
enum textarget, uint texture,
int level, uint xscale, uint yscale);
allows a rendering into the image of a texture object that has a lower
resolution than the framebuffer.
target, textarget, texture, and level correspond to the same
parameters for FramebufferTexture2D and have the same restrictions.
attachment corresponds to the same parameter for FramebufferTexture2D,
but must be COLOR_ATTACHMENTn.
xscale and yscale are multiplied by texture's width and height,
respectively, to produce the effective size of the attachment when
rendering. For example, a texture width of 128 with an xscale of 2 would
produce a color attachment with the effective width of 256. xscale and
yscale must be one of the value pairs in DOWNSAMPLE_SCALES_IMG. If the
xscale and yscale value pair is not available on the implementation,
then the error INVALID_VALUE is generated.
The implementation allocates an implicit color buffer for the same
internalformat as the specified texture, and widths and heights from the
specified texture level, multiplied by xscale and yscale. This buffer is
used as the target for rendering instead of the specified texture level.
The buffer is associated with the attachment and gets deleted after the
attachment is broken.
When the texture level is used as a source or destination for any
operation, the attachment is flushed, or when the attachment is broken,
an implicit downsample of the color data from the color buffer to the
texture level may be performed. After such a downsample, the contents
of the color buffer become undefined.
The operations which may cause a resolve include:
* Drawing with the texture bound to an active texture unit
* ReadPixels or CopyTex[Sub]Image* while the texture is
attached to the framebuffer
* CopyTex[Sub]Image*, Tex[Sub]Image*,
CompressedTex[Sub]Image* with the specified level as
destination
* GenerateMipmap
* Flush or Finish while the texture is attached to the
framebuffer
* BindFramebuffer while the texture is attached to the currently
bound framebuffer.
Whether each of the above cause a resolve or not is implementation-
dependent.
Add the following to the sub-section "Attaching Texture Images to a
Framebuffer" after the paragraph describing FramebufferTextureLayer:
The command
void FramebufferTextureLayerDownsampleIMG(
enum target, enum attachment,
uint texture, int level,
int layer, uint xscale, uint yscale);
allows a rendering into a single layer of a texture object that has a
lower resolution than the framebuffer. It operates like a combination of
FramebufferTexture2DDownsampleIMG and FramebufferTextureLayer; it allows
the developer to set scaling values and attaches a single layer of a
three-dimensional or two-dimensional array texture level.
target, attachment, level, xscale and yscale correspond to the same
parameters for FramebufferTexture2DDownsampleIMG and have the same
restrictions.
texture can only be a two-dimensional array texture, but otherwise has
the same restrictions as it does for FramebufferTextureLayer.
layer corresponds to the same parameter for FramebufferTextureLayer and
has the same restrictions.
In the sub-section "Effects of Attaching a Texture Image", change the bullet
list to the following:
* The value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is set to TEXTURE.
* The value of FRAMEBUFFER_ATTACHMENT_OBJECT_NAME is set to texture.
* The value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL is set to level.
* If FramebufferTexture2D is called and texture is a cube map texture,
then the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE is set
to textarget; otherwise it is set to the default (NONE).
* If FramebufferTextureLayer is called, then the value of FRAMEBUFFER_-
ATTACHMENT_TEXTURE_LAYER is set to layer; otherwise it is set to zero.
* If FramebufferTexture2DDownsampleIMG or
FramebufferTextureLayerDownsampleIMG is called, then the value of
FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG is set to {xscale, yscale};
otherwise it is set to {1, 1}.
In section 4.4.4 "Framebuffer Completeness", add the following bullet to the
end of the list in subsection "Framebuffer Attachment Completeness":
* If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the
value of FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG is supported by the
internal format of the attachment (see GetInternalFormativ in section
6.1.15).
In section 4.4.4 "Framebuffer Completeness", add the following bullet to the
end of the list in subsection "Whole Framebuffer Completeness":
* The value of FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG for all
attachments is {1,1}, or if not, the value of TEXTURE_SAMPLES_EXT or
RENDERBUFFER_SAMPLES for all attachments is zero.
FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG
Additions to Chapter 6 of the OpenGL ES 3.0 Specification:
Add the following bullet point to the list in Section 6.1.13 "Framebuffer
Object Queries" describing valid pname values when FRAMEBUFFER_ATTACHMENT_-
OBJECT_TYPE is TEXTURE:
* If pname is FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG, then params will
contain two integer values - the downsample scale pair for that
attachment.
Change the paragraph in Section 6.1.15 "Internal Format Queries" describing
valid target values to:
target indicates the usage of the internalformat, and must be one of
RENDERBUFFER, TEXTURE_2D, TEXTURE_CUBE_MAP or TEXTURE_2D_ARRAY.
Add the following paragraphs to Section 6.1.15 "Internal Format Queries" to
the paragraphs describing valid pname values:
If pname is NUM_DOWNSAMPLE_SCALES_IMG, the number of downscales that
would be returned by querying DOWNSAMPLE_SCALES_IMG is returned in params.
If pname is DOWNSAMPLE_SCALES_IMG, the available downscale pairs for the
format are written into params.
Formats that don't support downsampling will still return one valid
downsample scale pair - {1,1}. A value of one for NUM_DOWNSAMPLE_SCALES_IMG
will always mean no downscaling available, as {1,1} must be supported by
every format. Targets that don't support downscaling (e.g. RENDERBUFFER)
will return no downsample scale pairs.
Interactions with OpenGL ES 2.0
In section 4.4.5 of the OpenGL ES 2.0 Specification "Framebuffer
Completeness", subsection "Framebuffer Attachment Completeness", replace:
* All attached images have the same width and height.
FRAMEBUFFER_INCOMPLETE_DIMENSIONS
with:
* All attached images have the same value of width * xscale and
height * yscale.
FRAMEBUFFER_INCOMPLETE_DIMENSIONS
Interactions with OpenGL ES 3.1
If OpenGL ES 3.1 is supported, replace TEXTURE_SAMPLES_EXT with TEXTURE_-
SAMPLES, and add TEXTURE_2D_MULTISAMPLE to the list of valid targets for
GetInternalFormativ.
Interactions with EXT_multisampled_render_to_texture
If EXT_multisampled_render_to_texture is not supported:
- ignore references to TEXTURE_SAMPLES_EXT
- the sample counts returned by GetInternalFormativ with a target of
TEXTURE* will be the sample values available to be used with
FramebufferTexture2DMultisampleEXT
Dependencies on OpenGL ES 3.0
If OpenGL ES 3.0 or higher is not supported, ignore references to
glFramebufferTextureLayerDownsample and glGetIntegeri_v.
Interactions with EXT_color_buffer_float and EXT_color_buffer_half_float
If either of these extensions are supported, it is not guaranteed that
downscale of these formats is supported, but it may be - users will have to
check with the GetInternalFormat query.
This equally applies to any other additional render formats provided by
extension.
Errors
The error INVALID_VALUE is generated if FramebufferTextureLayerDownsampleIMG
or FramebufferTexture2DDownsampleIMG are are called with an <xscale> and
<yscale> value pair that isn't reported by DOWNSAMPLE_SCALES_IMG.
The error INVALID_ENUM is generated if FramebufferTextureLayerDownsampleIMG
or FramebufferTexture2DDownsampleIMG are called with an <attachment> that is
not COLOR_ATTACHMENTn.
New State
Add to Table 6.14 "Framebuffer (state per attachment point)"
Initial
Get Value Type Get Command Value Description Sec.
----------------- ----------- --------------------- ------- --------------- ----
FRAMEBUFFER_- 2 x Z+ GetFramebuffer- {1,1} Framebuffer 4.4.2
ATTACHMENT_- AttachmentParameteriv texture scale
TEXTURE_SCALE_IMG
New Implementation Dependent State
Add to Table 6.35 "Framebuffer Dependent Values"
Minimum
Get Value Type Get Command Value Description Sec.
----------------- ----------- ------------------ ------- --------------- ----
NUM_DOWNSAMPLE_- 2 x Z+ GetIntegerv 2 Number of 4.4.2
SCALES_IMG scale value
pairs available
DOWNSAMPLE_- 1* x 2 x Z+ GetIntegeri_v ** Scale value 4.4.2
SCALES_IMG pairs available
** At least {1,1} and {2,2} must be supported as a minimum to support this extension.
Example
GLint xDownscale = 1;
GLint yDownscale = 1;
// Select a downscale amount if possible
if (extension_is_supported("GL_IMG_framebuffer_downsample")
{
// Query the number of available scales
GLint numScales;
glGetIntegerv(GL_NUM_DOWNSAMPLE_SCALES_IMG, &numScales);
// 2 scale modes are supported as minimum, so only need to check for
// better than 2x2 if more modes are exposed.
if (numScales > 2)
{
// Try to select most aggressive scaling.
GLint bestScale = 1;
GLint tempScale[2];
GLint i;
for (i = 0; i < numScales; ++i)
{
glGetIntegeri_v(GL_DOWNSAMPLE_SCALES_IMG, i, tempScale);
// If the scaling is more aggressive, update our x/y scale values.
if (tempScale[0] * tempScale[1] > bestScale)
{
xDownscale = tempScale[0];
yDownscale = tempScale[1];
}
}
}
else
{
xDownscale = 2;
yDownscale = 2;
}
}
// Create depth texture. Depth and stencil buffers must be full size
GLuint depthTexture;
glGenTextures(1, &depthTexture);
glBindTexture(GL_TEXTURE_2D, depthTexture);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT16, width, height);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
// Create a full size RGBA texture with single mipmap level
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexStorage2D(GL_TEXTURE_2D, 0, GL_RGBA4, width, height);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
// Scale the width and height appropriately.
GLint scaledWidth = width / xDownscale;
GLint scaledHeight = height / yDownscale;
// Create a reduced size RGBA texture with single mipmap level
GLuint scaledTexture;
glGenTextures(1, &scaledTexture);
glBindTexture(GL_TEXTURE_2D, scaledTexture);
glTexStorage2D(GL_TEXTURE_2D, 0, GL_RGBA4, scaledWidth, scaledHeight);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
// Create framebuffer object, attach textures
GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D, depthTexture);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, texture, 0);
glFramebufferTexture2DDownsampleIMG(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
GL_TEXTURE_2D, scaledTexture, 0, xDownscale, yDownscale);
// Handle unsupported cases
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
...
}
// Draw to the texture
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
...
// Discard the depth renderbuffer contents if possible/available
if (extension_supported("GL_EXT_discard_framebuffer"))
{
GLenum discard_attachments[] = { GL_DEPTH_ATTACHMENT };
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, discard_attachments);
}
/*
Draw to the default framebuffer using the textures with various post
processing effects.
*/
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, scaledTexture);
...
Issues
1) Should renderbuffers be resolvable in this way too?
RESOLVED
No, renderbuffers are considered somewhat legacy and thus will
not be supported by this extension.
2) Should any scale values other than {1,1} be mandated as minimum?
RESOLVED
Yes, {2,2} will also be required. Implementations may support additional
values though, so a query is also added for other values.
3) What formats support downscaling?
RESOLVED
Formats that are guaranteed color-renderable by the core ES 3.1
specification, excluding integer and signed integer formats, support all
available downscale modes. Other formats only support {1,1} (no
downscaling).
4) What should happen if an application calls GetInternalFormativ with a
target of TEXTURE* (not TEXTURE_2D_MULTISAMPLE)?
RESOLVED
For standard OpenGL ES, NUM_SAMPLE_COUNTS should be zero. However, if
EXT_multisampled_render_to_texture is supported, valid configurations
for FramebufferTexture2DMultisampleEXT should be returned here.
Revision History
Revision 1, 2014/08/27
- First draft
Revision 2, 2015/03/16
- Mandated {2,2} as a required downsample scale.
- Coupled x and y scale values into pairs
Revision 3, 2015/03/19
- Moved framebuffer completeness information to correct (whole framebuffer
completeness) section, and corrected wording.
- Added note about minimum support in the overview.
Revision 4, 2015/03/19
- Added a specific revision of the OpenGL ES 3.0 specification
- Added an error that only COLOR_ATTACHMENTn can be used as an attachment
point
Revision 5, 2015/06/02
- Added internalformat query capability, so that formats can opt into
downscaling support
- Added section on downscaling to per-fragment operations.
- Added issue about what formats support downscaling.
- Restricted layer downscaling to 2D array textures.
Revision 6, 2015/06/03
- Fixed typo in incomplete framebuffer condition
- Added a bullet point to describe the FRAMEBUFFER_ATTACHMENT_TEXTURE_-
SCALE_IMG parameter to GetFramebufferAttachmentiv
- Clarified targets to GetInternalFormativ
Revision 7, 2015/06/17
- Clarified interactions with EXT_color_buffer_float and
EXT_color_buffer_half_float
Revision 8, 2015/06/22
- Added NUM_DOWNSAMPLE_SCALES_IMG as a parameter to GetInternalFormativ
- Added framebuffer attachment incomplete message and removed error when
scale pair isn't supported by textures' internalformat, as
internalformat is not necessarily known at attachment time.
Revision 9, 2015/08/19
- Assigned enum values
Revision 10, 2015/08/20
- Allowed DOWNSAMPLE_SCALES_IMG to be used with GetIntegerv/GetInteger64v
Revision 11, 2015/12/18
- Fixed example - "tempScale" is an array so doesn't need to be dereferenced.