Name EXT_shader_framebuffer_fetch Name Strings GL_EXT_shader_framebuffer_fetch GL_EXT_shader_framebuffer_fetch_non_coherent Contact Benj Lipchak, Apple (lipchak 'at' apple.com) Contributors Francisco Jerez, Intel Status Complete Version Last Modified Date: September 6, 2018 Author Revision: 8 Number OpenGL ES Extension #122 OpenGL Extension #520 Dependencies OpenGL 2.0 or OpenGL ES 2.0 is required. This specification is written against the OpenGL ES 2.0.24 and OpenGL ES 3.0.4 specifications. This extension is written against the OpenGL ES Shading Language 1.0.17 and OpenGL ES Shading Language 3.00.3 specifications. OpenGL 2.0, OpenGL 3.0, OpenGL 4.0, OpenGL 4.5, OpenGL ES 2.0, OpenGL ES 3.0, OpenGL ES 3.1 and OpenGL ES 3.2 affect the definition of this extension. ARB_sample_shading and OES_sample_shading interact with 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. This extension provides two alternative name strings: - GL_EXT_shader_framebuffer_fetch guarantees full coherency between framebuffer reads and writes. If this extension string is exposed, the result of reading from the framebuffer from a fragment shader invocation is guaranteed to reflect values written by any previous overlapping samples in API primitive order, unless requested otherwise in the shader source using the noncoherent layout qualifier. - GL_EXT_shader_framebuffer_fetch_non_coherent provides limited implicit coherency guarantees. Instead, the application is expected to call the FramebufferFetchBarrierEXT command for previous framebuffer writes to become visible to subsequent fragment shader invocations. For this extension to give well-defined results applications may have to split rendering into multiple passes separated with FramebufferFetchBarrierEXT calls. The functionality provided by this extension is requested in the shader source using the noncoherent layout qualifier. 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, but has no additional implications on fragment shader input variables which may still be interpolated per pixel by the implementation. 2. How does the use of gl_LastFragData interact with fragment discard? RESOLVED: Hardware may not necessarily support discarding on sample granularity depending on API version and extension support. 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 where support for per-sample discard is not provided by the GL. 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. If an overlapping specification guarantees well-defined results for shaders that execute discard with sample granularity (e.g. ARB_sample_shading), this extension won't reverse that guarantee, instead the boolean query FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT defined by this extension will return TRUE for consistency with current specifications. 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. 6. How does this extension interact with sRGB rendering? RESOLVED: If the current GL state would cause the corresponding destination color to be converted from sRGB to linear at input to blending, gl_LastFragData or fragment outputs with the inout storage qualifier will contain framebuffer values converted from sRGB to linear upon entry to the fragment shader. 7. How does this extension interact with derivative built-in functions? RESOLVED: There is no direct interaction in principle, but because the result of framebuffer fetch is undefined for helper invocations, derivative functions may give non-deterministic results when the argument is dependent on values read from the framebuffer. To overcome this limitation the application may be able to calculate the derivative of gl_HelperInvocation in order to determine whether any of the invocations involved in the calculation are helper invocations, which would invalidate the result of the same derivative applied to any expression dependent on values read from the framebuffer. In particular, if either dFdx(float(gl_HelperInvocation)) or dFdy(float(gl_HelperInvocation)) is zero, the corresponding derivative of a value read from the framebuffer should be well-defined. 8. Should we require the behavior of framebuffer fetch to be well-defined for helper invocations in order to support calculating derivatives of color outputs without restrictions? RESOLVED: Not in this extension. It would be compelling from the perspective of the API, and likely more consistent with the current behavior of texture sampling and image loads for helper invocations, but hardware support may be limited. With the non-coherent variant of this extension there is the additional difficulty that derivatives could still give non-deterministic results, because there is no way for the application to determine whether there will be overlap between helper invocations and previous rendering done in the same pass, since the set of helper invocations executed during rendering is fully defined by the implementation. 9. How should the implementation behave where framebuffer fetch coherency cannot be enabled selectively for each fragment output due to hardware or software limitations? RESOLVED: Because the behavior specified for coherent framebuffer fetch outputs is a strict subset of the behavior of non-coherent outputs, the implementation is free to ignore any noncoherent layout qualifiers and enable coherency globally when the fragment shader bound to the pipeline has any color outputs requiring framebuffer fetch coherency. 10. Should the current coherent memory qualifier be reused to indicate whether the application requires framebuffer fetch coherency for a given fragment output? RESOLVED: No, because that would imply breaking GLSL source-level compatibility with earlier versions of the EXT_shader_framebuffer_fetch extension. That said, it may make sense to reconsider this syntactic compromise if this extension is used as starting point for another specification text (e.g. a derived ARB/KHR extension). New Procedures and Functions [[ The following applies if EXT_shader_framebuffer_fetch_non_coherent is supported. ]] void FramebufferFetchBarrierEXT(void); New Tokens Accepted by the parameter of GetBooleanv, GetIntegerv, GetFloatv, and GetDoublev: FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52 New Builtin Variables [[ The following applies to OpenGL Shading Language 1.1 and 1.2 only. ]] vec4 gl_LastFragData[gl_MaxDrawBuffers]; [[ The following applies to OpenGL ES Shading Language 1.0 only. ]] 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." [[ The following applies if EXT_shader_framebuffer_fetch_non_coherent is supported. ]] Append new paragraph at the end of section 3.8.2, page 197 ("Shader Execution"): "The command void FramebufferFetchBarrierEXT(void); specifies a boundary between passes when reading existing framebuffer data from fragment shaders via the gl_LastFragData built-in variable. Previous framebuffer object writes regardless of the mechanism (including clears, blits and primitive rendering) are guaranteed to be visible to subsequent fragment shader invocations that read from the framebuffer once FramebufferFetchBarrierEXT is executed." [[ The following applies if both EXT_shader_framebuffer_fetch and EXT_shader_framebuffer_fetch_non_coherent are supported. ]] "Because the implementation guarantees coherency of framebuffer reads and writes for color outputs not explicitly marked with the noncoherent layout qualifier, calling the FramebufferFetchBarrierEXT command is not required unless the application wishes to manage memory ordering of framebuffer reads and writes explicitly, which may provide better performance on some implementations in cases where rendering can be split into multiple passes with non-self-overlapping geometry." [[ The following applies to either variant of the extension unless specified otherwise in the interactions sections. ]] 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" Add a new section 4.1.lastfragcolor (Fragment Data Input) - immediately before section 4.1.4 (Stencil Test): Prior to fragment shading, if GL_EXT_shader_framebuffer_fetch is enabled, gl_LastFragData[] is populated with the value last written to the framebuffer at the same (x,y,sample) position. If the framebuffer attachment corresponding to a given element of gl_LastFragData[] has a fixed-point format, each color component undergoes a conversion to floating-point first. This conversion must leave the values 0 and 1 invariant. [[If GL_EXT_sRGB is supported]] If the value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING{_EXT} for the framebuffer attachment corresponding to a given element of gl_LastFragData[] is SRGB, [[If GL_EXT_sRGB_write_control is supported]] and FRAMEBUFFER_SRGB_EXT is enabled, [[End GL_EXT_sRGB_write_control]] the R, G, and B destination color values (after conversion from fixedpoint to floating-point) are considered to be encoded for the sRGB color space and hence must be linearized first. Each R, G, and B component is converted in the same fashion described for sRGB texture components in section 3.8.16. [[End GL_EXT_sRGB]] 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 3.0.4 Specification, Chapter 3 Append new paragraphs at the end of the "Shader Outputs" subsection under section 3.9.2, Shader Execution, page 171: "Prior to fragment shading, fragment outputs declared inout are populated with the value last written to the framebuffer at the same (x,y,sample) position. If the framebuffer attachment corresponding to an inout fragment output has a fixed-point format, each color component undergoes a conversion to floating-point first. This conversion must leave the values 0 and 1 invariant. Reading from a user-defined fragment output declared inout causes the shader to be evaluated per-sample, since the framebuffer potentially contains different color values for each sample. If the value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING{_EXT} for the framebuffer attachment corresponding to a given inout fragment output is SRGB (see section 6.1.13)," [[If GL_EXT_sRGB_write_control is supported]] "and FRAMEBUFFER_SRGB_EXT is enabled," [[End GL_EXT_sRGB_write_control]] "the R, G, and B destination color values (after conversion from fixed-point to floating-point) are considered to be encoded for the sRGB color space and hence must be linearized first. Each R, G, and B component is converted in the same fashion described for sRGB texture components in section 3.8.16." [[ The following applies if EXT_shader_framebuffer_fetch_non_coherent is supported. ]] "The command void FramebufferFetchBarrierEXT(void); specifies a boundary between passes when reading existing framebuffer data from fragment shaders via inout fragment outputs. Previous framebuffer object writes regardless of the mechanism (including clears, blits and primitive rendering) are guaranteed to be visible to subsequent fragment shader invocations that read from the framebuffer once FramebufferFetchBarrierEXT is executed." [[ The following applies if both EXT_shader_framebuffer_fetch and EXT_shader_framebuffer_fetch_non_coherent are supported. ]] "Because the implementation guarantees coherency of framebuffer reads and writes for color outputs not explicitly marked with the noncoherent layout qualifier, calling the FramebufferFetchBarrierEXT command is not required unless the application wishes to manage memory ordering of framebuffer reads and writes explicitly, which may provide better performance on some implementations in cases where rendering can be split into multiple passes with non-self-overlapping geometry." 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 the Shading Language, 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 or layout qualifier." Changes to the OpenGL ES Shading Language 1.0.17 Specification, Chapter 4 [[ The following applies if EXT_shader_framebuffer_fetch_non_coherent is supported. ]] Add a new Section 4.x (Layout Qualifiers) as follows: "4.x Layout Qualifiers Layout qualifiers can appear with an individual variable declaration: ; : layout( ) : comma separated list of Declarations of layouts can only be made at global scope, and only where indicated in the following subsection; their details are specific to what the declaration interface is, and are discussed individually. The tokens in any are identifiers, not keywords. Generally they can be listed in any order. Order-dependent meanings exist only if explicitly called out below. Similarly, these identifiers are not case-sensitive, unless explicitly noted otherwise. 4.x.1 Output Layout Qualifiers Fragment shaders may specify the following layout qualifier only for redeclaring the built-in gl_LastFragData array. The allowed layout qualifier identifiers for gl_LastFragData are: : noncoherent Non-coherent framebuffer fetch outputs have relaxed memory ordering requirements and may provide better performance on some implementations, but they require FramebufferFetchBarrierEXT to be called explicitly for the contents rendered to a color attachment to be visible to subsequent fragment shader invocations. Redeclarations are done as follows: layout(noncoherent) mediump vec4 gl_LastFragData[gl_MaxDrawBuffers];" 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." [[ The following applies if EXT_shader_framebuffer_fetch is supported. ]] "Unless it has been redeclared with the noncoherent layout qualifier, gl_LastFragData contains the most recent value written to the attachments bound to each color output at the current sample location. Access to gl_LastFragData is optional and can be enabled by #extension GL_EXT_shader_framebuffer_fetch : Where is as specified in section 3.4. A new preprocessor define is added to the Shading Language: #define GL_EXT_shader_framebuffer_fetch 1" [[ The following applies if EXT_shader_framebuffer_fetch_non_coherent is supported. ]] "If it has been redeclared with the noncoherent layout qualifier, gl_LastFragData contains the most recent value written to the attachments bound to each color output at the current sample location as long as FramebufferFetchBarrierEXT has been executed between the last command that updated the same location of the framebuffer attachment and the current draw call. Its value is undefined for any outputs whose contents at the current sample location have been modified since the last FramebufferFetchBarrierEXT call. Access to gl_LastFragData and the ability to use the layout(noncoherent) qualifier are optional and can be enabled by #extension GL_EXT_shader_framebuffer_fetch_non_coherent : Where is as specified in section 3.4. A new preprocessor define is added to the Shading Language: #define GL_EXT_shader_framebuffer_fetch_non_coherent 1" [[ The following applies to either variant of the extension but shall be omitted where precision qualifiers are not supported. ]] "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." [[ The following applies if EXT_shader_framebuffer_fetch_non_coherent is supported. ]] "Unless the GL_EXT_shader_framebuffer_fetch extension has been enabled in addition, it's an error to use gl_LastFragData if it hasn't been explicitly redeclared with layout(noncoherent)." Changes to the OpenGL ES Shading Language 1.0.17 Specification, Chapter 8 Add after paragraph 2 of section 8.7, Texture Lookup Functions, page 57 ("Functions containing the bias parameter [...]"): "Results are undefined if the coordinates passed to any of the built-in functions below that compute an implicit LOD value are calculated based on the result of reading from gl_LastFragData, and the texture bound to the specified sampler is mip-mapped." Changes to the OpenGL Shading Language 1.10 Specification, Chapter 8 [[ The following applies in addition to the changes given above for the same chapter of the OpenGL ES Shading Language 1.0.17 Specification. ]] Append at the end of section 8.8, Fragment Processing Functions, page 59: "The result of the built-in derivative functions dFdx, dFdy and fwidth is undefined if the value passed as argument was calculated based on the result of reading from 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 7 of section 4.3.6: "Fragment outputs output per-fragment data and are declared using the out or inout storage qualifier. It is a compile-time error to use auxiliary storage qualifiers or interpolation qualifiers on an output in a fragment shader [...]" and append new paragraphs at the end of the same section: [[ The following applies if EXT_shader_framebuffer_fetch_non_coherent is supported. ]] "Fragment outputs declared inout may specify the following layout qualifier: : noncoherent Non-coherent framebuffer fetch outputs have relaxed memory ordering requirements and may provide better performance on some implementations, but they require FramebufferFetchBarrierEXT to be called explicitly for the contents rendered to a color attachment to be visible to subsequent fragment shader invocations." [[ The following applies if EXT_shader_framebuffer_fetch is supported. ]] "Upon entry to the fragment shader, fragment outputs declared inout not qualified with the noncoherent layout qualifier will contain the most recent value written to the same framebuffer attachment at the current sample location. This behavior and the ability to use the inout qualifier at global scope in a fragment shader is optional and can be enabled by #extension GL_EXT_shader_framebuffer_fetch : Where is as specified in section 3.4. A new preprocessor define is added to the Shading Language: #define GL_EXT_shader_framebuffer_fetch 1" [[ The following applies if EXT_shader_framebuffer_fetch_non_coherent is supported. ]] "Upon entry to the fragment shader, fragment outputs declared inout qualified with the noncoherent layout qualifier will contain the most recent value written to the same framebuffer attachment at the current sample location, as long as FramebufferFetchBarrierEXT has been executed between the last command that updated the framebuffer location and the current draw call. The initial value is undefined for any fragment outputs declared inout whose contents at the current sample location have been modified since the last FramebufferFetchBarrierEXT call. This behavior and the ability to use the inout and layout(noncoherent) qualifiers at global scope in a fragment shader are optional and can be enabled by #extension GL_EXT_shader_framebuffer_fetch_non_coherent : Where is as specified in section 3.4. A new preprocessor define is added to the Shading Language: #define GL_EXT_shader_framebuffer_fetch_non_coherent 1" [[ The following applies if EXT_shader_framebuffer_fetch_non_coherent is supported. ]] "It is an error to declare an inout fragment output not qualified with layout(noncoherent) if the GL_EXT_shader_framebuffer_fetch extension hasn't been enabled." Changes to the OpenGL ES Shading Language 3.00.3 Specification, Chapter 7 [[ The following shall be omitted if the changes given below for the same chapter of the OpenGL ES Shading Language 3.10.4 Specification apply. ]] Append at the end of section 7.2, Fragment Shader Special Variables, page 82: "A helper invocation is a fragment shader invocation that is created solely for the purposes of evaluating derivatives for the built-in functions texture() (section 8.9 "Texture Functions"), dFdx(), dFdy(), and fwidth() for other non-helper fragment shader invocations. Fragment shader helper invocations execute the same shader code as non-helper invocations, but will not have side effects that modify the framebuffer or other shader-accessible memory. In particular fragments corresponding to helper invocations are discarded when shader execution is complete, without updating the framebuffer. The values returned when reading from the framebuffer via inout fragment outputs are undefined for helper invocations. Helper invocations may be generated for pixels not covered by a primitive being rendered. While fragment shader inputs qualified with "centroid" are normally required to be sampled in the intersection of the pixel and the primitive, the requirement is ignored for such pixels since there is no intersection between the pixel and primitive. Helper invocations may also be generated for fragments that are covered by a primitive being rendered when the fragment is killed by early fragment tests or where the implementation is able to determine that executing the fragment shader would have no effect other than assisting in computing derivatives for other fragment shader invocations. The set of helper invocations generated when processing any set of primitives is implementation-dependent." Changes to the OpenGL ES Shading Language 3.10.4 Specification, Chapter 7 Modify the first bullet point of paragraph 11 of section 7.1.2, Fragment Shader Special Variables, page 96: "* Fragments corresponding to helper invocations are discarded when shader execution is complete, without updating the framebuffer. The values returned when reading from the framebuffer via inout fragment outputs are undefined for helper invocations." Interactions with OpenGL 2.0 If OpenGL 2.0 is supported, all changes given above for the OpenGL ES 2.0.24 and OpenGL ES Shading Language 1.0.17 specifications shall be applied, in addition to any changes given specifically for the OpenGL Shading Language 1.10 Specification. References to precision qualifiers shall be omitted. Interactions with OpenGL 3.0 and later If OpenGL 3.0 is supported, all changes given above for the OpenGL ES 3.0.4 and OpenGL ES Shading Language 3.00.3 specifications shall be applied. Changes given for earlier OpenGL ES and OpenGL ES Shading Language versions shall be ignored. References to auxiliary storage qualifiers shall be omitted if they are not supported by the Shading Language. Interactions with OpenGL 4.0 and later The interaction described below with ARB_sample_shading applies in addition to any interactions enumerated for OpenGL 3.0 and above. Interactions with OpenGL 4.5 and later The changes given above for the OpenGL Shading Language 3.10.4 Specification shall be applied in addition to any interactions enumerated for OpenGL 4.0 and above. Interactions with OpenGL ES 2.0 If OpenGL ES 2.0 is supported, apply all changes given above for the OpenGL ES 2.0.24 and OpenGL ES Shading Language 1.0.17 specifications. Interactions with OpenGL ES 3.0 and later If OpenGL ES 3.0 is supported, all changes given above for the OpenGL ES 3.0.4 and OpenGL ES Shading Language 3.00.3 specifications shall be applied. Changes given for earlier OpenGL ES and OpenGL ES Shading Language versions shall be ignored. References to auxiliary storage qualifiers shall be omitted if they are not supported by the Shading Language. Interactions with OpenGL ES 3.1 and later The changes given above for the OpenGL Shading Language 3.10.4 Specification shall be applied in addition to any interactions enumerated for OpenGL ES 3.0 and above. Interactions with OpenGL ES 3.2 and later The interaction described below with OES_sample_shading applies in addition to any interactions enumerated for OpenGL ES 3.1 and above. 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. Interactions with ARB_sample_shading and OES_sample_shading The FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT query defined above is guaranteed to return TRUE if any of these extensions is supported, since they already provide well-defined behavior for discard jumps with sample granularity. Revision History Version 8, 2018/09/06 - Replace non-ASCII quote characters. Version 7, 2017/11/13 - Specify interactions with desktop OpenGL APIs. - Specify interaction with ARB/OES_sample_shading and unextended GL versions that provide the same functionality. Clarify resolution of multisampling-related issues to avoid contradicting recent versions of the spec. - Explicitly require per-sample evaluation of the fragment shader when an inout output is read in OpenGL ES 3.0 and above. - Specify undefined behavior of helper invocations in OpenGL ES 3.0 and above. Add discussion related to derivative computations in the issues section. - Specify undefined behavior of texture lookup functions that compute implicit derivatives in OpenGL (ES) 2.0. - Define EXT_shader_framebuffer_fetch_non_coherent variant of the extension. Add FramebufferFetchBarrierEXT command. Define noncoherent layout qualifier for finer-grained control of framebuffer fetch coherency. Version 6, 2017/10/04 - Clarified how gl_LastFragData is populated. Version 5, 2016/09/08 - Added preprocessor defines. 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.