Name EXT_shader_framebuffer_fetch Name Strings GL_EXT_shader_framebuffer_fetch Contact Benj Lipchak, Apple (lipchak 'at' apple.com) Status Complete Version Last Modified Date: May 28, 2013 Author Revision: 4 Number OpenGL ES Extension #122 Dependencies OpenGL ES 2.0 is required. This specification is written against the OpenGL ES 2.0.24 specification. This extension is written against the OpenGL ES Shading Language 1.0.17 specification. OpenGL ES 3.0 affects the definition of this extension. Overview Conventional OpenGL blending provides a configurable series of operations that can be used to combine the output values from a fragment shader with the values already in the framebuffer. While these operations are suitable for basic image compositing, other compositing operations or operations that treat fragment output as something other than a color (normals, for instance) may not be expressible without multiple passes or render-to-texture operations. This extension provides a mechanism whereby a fragment shader may read existing framebuffer data as input. This can be used to implement compositing operations that would have been inconvenient or impossible with fixed-function blending. It can also be used to apply a function to the framebuffer color, by writing a shader which uses the existing framebuffer color as its only input. Issues 1. How is framebuffer data treated during multisample rendering? RESOLVED: Reading the value of gl_LastFragData produces a different result for each sample. This implies that all or part of the shader be run once for each sample. Input values to the shader from existing variables in GLSL ES remain identical across samples. 2. How does the use of gl_LastFragData interact with fragment discard? RESOLVED: Hardware may not necessarily support discarding on sample granularity. Therefore, three options were considered for this functionality: A) Allow discard based on variables calculated using the framebuffer color when multisample rasterization is disabled, but disallow discard in this manner when multisample rasterization is enabled. B) Restrict usage of the framebuffer color until it is known whether or not the pixel will be discarded. C) Allow undefined results for fragment shaders that discard on a per-sample basis on hardware that doesn't support it. This extension has chosen option C. Restricting orthogonality of fragment shaders between single-sample and multisample rendering is undesirable, as is restricting usage of the framebuffer color, which can generally only be done with detailed flow-control analysis. 3. What is the precision of gl_LastFragData in practice? RESOLVED: Three options were considered for this functionality: A) gl_LastFragData is always mediump. B) gl_LastFragData takes the precision most closely matching the actual storage format of the framebuffer. C) Allow redeclaration of gl_LastFragData in order to change its precision. This extension has chosen option C. A fixed precision per option A increases the likelihood of redundant conversion operations in the shader, and option B does not provide for clear behavior with regard to the precision of intermediate results from calculations using the framebuffer color. 4. How does this extension iteract with conventional blending? RESOLVED: There is no interaction. The two remain orthogonal. The rest of the pipeline continues as usual after the fragment shader stage. 5. How does this extension work in ES 3.0? RESOLVED: Differently than in ES 2.0. The built-in fragment outputs of ES 2.0 are replaced in #version 300 es shaders by user-declared outputs, to accomodate integer and MRT framebuffers. Three options were considered: A) Add built-ins similar to gl_LastFragData. B) Add a layout to mark user-declared fragment outputs as having defined content on entry to fragment shader. C) Allow marking user-declared fragment outputs as "inout". This extension has chosen option C. Adding built-ins per option A is unwieldy for MRT framebuffers with mixed attachment types and precisions. Options B and C are semantically identical, but C requires fewer modifications to the specification and to user shaders. Note that the inout qualifier is not allowed for re-declaring existing fragment outputs such as gl_FragDepth. New Procedures and Functions None New Tokens Accepted by the parameter of GetBooleanv, GetIntegerv, GetFloatv, and GetDoublev: FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52 New Builtin Variables mediump vec4 gl_LastFragData[gl_MaxDrawBuffers] Changes to the OpenGL ES 2.0.24 Specification, Chapter 3 Remove the last sentence of Paragraph 2 of Section 3.8.1, page 84 ("These built-in varying variables include [...]" and add: These built-in varying variables include the fragment's position, eye z coordinate, and front-facing flag, as well as the last data or color value written to the framebuffer. When the value of SAMPLE_BUFFERS is 1 and the current framebuffer color is accessed in the fragment shader, the fragment shader will be invoked separately for each covered sample and a separate value for the previous framebuffer color will be provided for each sample." Add a new subsection to section 3.8.2, page 87 ("Shader Execution"): "Discard Fragment shaders may conditionally abandon operations using the discard keyword. However, the ability of hardware to support abandoning operations on a single sample when the shader is invoked once for each covered sample is implementation-dependent. This capability can be determined by calling GetBooleanv with the symbolic constant FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT. If FALSE is returned, results from shaders which discard based on per-sample logic are undefined." Changes to the OpenGL ES 2.0.24 Specification, Chapter 4 Replace first element of Figure 4.1, page 90 ("Fragment + Associated Data"): "Fragment (or sample) + Associated Data" New Implementation Dependent State Add to table 6.19 (Implementation Dependent Values (cont.)): Get Value Type Get Command Minimum Value Description Section --------- ---- ----------- ------------- -------------- ------- FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT B GetBooleanv - Samples may be 3.8.2 discarded individually Changes to the OpenGL ES Shading Language 1.0.17 Specification, Chapter 3 Remove Paragraph 2 of section 3.8, page 17, Identifiers ("Identifiers starting with "gl_" are reserved [...]") and add: "Identifiers starting with "gl_" are reserved for use by OpenGL ES, and may not be declared in a shader as either a variable or a function. However, as noted in the specification, certain predeclared "gl_" names are allowed to be redeclared in a shader for the specific purpose of changing their precision qualifier." Changes to the OpenGL ES Shading Language 1.0.17 Specification, Chapter 7 Add after the last sentence of Paragraph 2 of Section 7.2, page 60, Fragment Shader Special Variables ("These variables may be written to more [...]"): "... To access the existing framebuffer values (e.g., to implement a complex blend operation inside the shader), fragment shaders should use the read-only input array gl_LastFragData. gl_LastFragData returns the value written by the most recent fragment at the same position. Access to gl_LastFragData is optional, and must be enabled by #extension GL_EXT_shader_framebuffer_fetch : Where is as specified in section 3.3. By default, gl_LastFragData is declared with the mediump precision qualifier. This can be changed by redeclaring the corresponding variables with the desired precision qualifier. Redeclarations are done as follows // Redeclaration that changes nothing is allowed mediump vec4 gl_LastFragData[gl_MaxDrawBuffers]; // All the following are allowed redeclaration that change behavior lowp vec4 gl_LastFragData[gl_MaxDrawBuffers]; highp vec4 gl_LastFragData[gl_MaxDrawBuffers]; Redeclarations must not otherwise alter the declared type or array size of gl_LastFragData." Changes to the OpenGL ES Shading Language 3.00.3 Specification, Chapter 4 Modify Paragraph 2 of section 4.3.6: "Except in the fragment stage, there is not an inout storage qualifier at global scope for declaring a single variable name as both input and output [...]" Modify Paragraph 5 of section 4.3.6: "Fragment outputs output per-fragment data and are declared using the out or inout storage qualifier. It is an error to use centroid out or centroid inout in a fragment shader [...]" and append new paragraph: "Upon entry to the fragment shader, fragment outputs declared as inout will contain the value written by the most recent fragment at the same position. This behavior, and the ability to use the inout qualifier at global scope in a fragment shader, is optional and must be enabled by #extension GL_EXT_shader_framebuffer_fetch : Where is as specified in section 3.4." Interactions with OES_standard_derivatives Results from shaders which use the built-in derivative functions dFdx, dFdy, and fwidth on variables calculated using the current framebuffer color are undefined. Revision History Version 4, 2013/05/28 - Added ES3 interaction as requested in Bug 10236 Version 3, 2012/09/24 - Remove obsolete issue 3 about derivatives Version 2, 2012/06/21 - Fix MULTISAMPLE enabled -> SAMPLE_BUFFERS = 1, recast from APPLE to multivendor EXT, clarify that gl_LastFragData reflects value written by previous pixel at same coordinates. Version 1, 2012/06/01 - Conversion from ARB_sync to APPLE_sync for ES.