Erik Dahlström | ea7a212 | 2014-11-17 16:15:57 +0100 | [diff] [blame] | 1 | Name |
| 2 | |
| 3 | EXT_shader_framebuffer_fetch |
| 4 | |
| 5 | Name Strings |
| 6 | |
| 7 | GL_EXT_shader_framebuffer_fetch |
| 8 | |
| 9 | Contact |
| 10 | |
| 11 | Benj Lipchak, Apple (lipchak 'at' apple.com) |
| 12 | |
| 13 | Status |
| 14 | |
| 15 | Complete |
| 16 | |
| 17 | Version |
| 18 | |
| 19 | Last Modified Date: May 28, 2013 |
| 20 | Author Revision: 4 |
| 21 | |
| 22 | Number |
| 23 | |
| 24 | OpenGL ES Extension #122 |
| 25 | |
| 26 | Dependencies |
| 27 | |
| 28 | OpenGL ES 2.0 is required. |
| 29 | |
| 30 | This specification is written against the OpenGL ES 2.0.24 specification. |
| 31 | This extension is written against the OpenGL ES Shading Language 1.0.17 |
| 32 | specification. |
| 33 | |
| 34 | OpenGL ES 3.0 affects the definition of this extension. |
| 35 | |
| 36 | Overview |
| 37 | |
| 38 | Conventional OpenGL blending provides a configurable series of operations |
| 39 | that can be used to combine the output values from a fragment shader with |
| 40 | the values already in the framebuffer. While these operations are |
| 41 | suitable for basic image compositing, other compositing operations or |
| 42 | operations that treat fragment output as something other than a color |
| 43 | (normals, for instance) may not be expressible without multiple passes or |
| 44 | render-to-texture operations. |
| 45 | |
| 46 | This extension provides a mechanism whereby a fragment shader may read |
| 47 | existing framebuffer data as input. This can be used to implement |
| 48 | compositing operations that would have been inconvenient or impossible with |
| 49 | fixed-function blending. It can also be used to apply a function to the |
| 50 | framebuffer color, by writing a shader which uses the existing framebuffer |
| 51 | color as its only input. |
| 52 | |
| 53 | Issues |
| 54 | |
| 55 | 1. How is framebuffer data treated during multisample rendering? |
| 56 | |
| 57 | RESOLVED: Reading the value of gl_LastFragData produces a different |
| 58 | result for each sample. This implies that all or part of the shader be run |
| 59 | once for each sample. Input values to the shader from existing variables |
| 60 | in GLSL ES remain identical across samples. |
| 61 | |
| 62 | 2. How does the use of gl_LastFragData interact with fragment discard? |
| 63 | |
| 64 | RESOLVED: Hardware may not necessarily support discarding on sample |
| 65 | granularity. Therefore, three options were considered for this |
| 66 | functionality: |
| 67 | |
| 68 | A) Allow discard based on variables calculated using the framebuffer |
| 69 | color when multisample rasterization is disabled, but disallow |
| 70 | discard in this manner when multisample rasterization is enabled. |
| 71 | |
| 72 | B) Restrict usage of the framebuffer color until it is known whether |
| 73 | or not the pixel will be discarded. |
| 74 | |
| 75 | C) Allow undefined results for fragment shaders that discard on a |
| 76 | per-sample basis on hardware that doesn't support it. |
| 77 | |
| 78 | This extension has chosen option C. Restricting orthogonality of fragment |
| 79 | shaders between single-sample and multisample rendering is undesirable, as |
| 80 | is restricting usage of the framebuffer color, which can generally only be |
| 81 | done with detailed flow-control analysis. |
| 82 | |
| 83 | 3. What is the precision of gl_LastFragData in practice? |
| 84 | |
| 85 | RESOLVED: Three options were considered for this functionality: |
| 86 | |
| 87 | A) gl_LastFragData is always mediump. |
| 88 | |
| 89 | B) gl_LastFragData takes the precision most closely matching the |
| 90 | actual storage format of the framebuffer. |
| 91 | |
| 92 | C) Allow redeclaration of gl_LastFragData in order to change its |
| 93 | precision. |
| 94 | |
| 95 | This extension has chosen option C. A fixed precision per option A |
| 96 | increases the likelihood of redundant conversion operations in the shader, |
| 97 | and option B does not provide for clear behavior with regard to the |
| 98 | precision of intermediate results from calculations using the |
| 99 | framebuffer color. |
| 100 | |
| 101 | 4. How does this extension iteract with conventional blending? |
| 102 | |
| 103 | RESOLVED: There is no interaction. The two remain orthogonal. The rest |
| 104 | of the pipeline continues as usual after the fragment shader stage. |
| 105 | |
| 106 | |
| 107 | 5. How does this extension work in ES 3.0? |
| 108 | |
| 109 | RESOLVED: Differently than in ES 2.0. |
| 110 | |
| 111 | The built-in fragment outputs of ES 2.0 are replaced in #version 300 es |
| 112 | shaders by user-declared outputs, to accomodate integer and MRT |
| 113 | framebuffers. Three options were considered: |
| 114 | |
| 115 | A) Add built-ins similar to gl_LastFragData. |
| 116 | |
| 117 | B) Add a layout to mark user-declared fragment outputs as having |
| 118 | defined content on entry to fragment shader. |
| 119 | |
| 120 | C) Allow marking user-declared fragment outputs as "inout". |
| 121 | |
| 122 | This extension has chosen option C. Adding built-ins per option A is |
| 123 | unwieldy for MRT framebuffers with mixed attachment types and precisions. |
| 124 | Options B and C are semantically identical, but C requires fewer |
| 125 | modifications to the specification and to user shaders. Note that the |
| 126 | inout qualifier is not allowed for re-declaring existing fragment outputs |
| 127 | such as gl_FragDepth. |
| 128 | |
| 129 | New Procedures and Functions |
| 130 | |
| 131 | None |
| 132 | |
| 133 | New Tokens |
| 134 | |
| 135 | Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv, |
| 136 | and GetDoublev: |
| 137 | |
| 138 | FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52 |
| 139 | |
| 140 | New Builtin Variables |
| 141 | |
| 142 | mediump vec4 gl_LastFragData[gl_MaxDrawBuffers] |
| 143 | |
| 144 | Changes to the OpenGL ES 2.0.24 Specification, Chapter 3 |
| 145 | |
| 146 | Remove the last sentence of Paragraph 2 of Section 3.8.1, page 84 ("These |
| 147 | built-in varying variables include [...]" and add: |
| 148 | |
| 149 | These built-in varying variables include the fragment's position, eye z |
| 150 | coordinate, and front-facing flag, as well as the last data or color value |
| 151 | written to the framebuffer. When the value of SAMPLE_BUFFERS is 1 and the |
| 152 | current framebuffer color is accessed in the fragment shader, the fragment |
| 153 | shader will be invoked separately for each covered sample and a separate |
| 154 | value for the previous framebuffer color will be provided for each sample." |
| 155 | |
| 156 | Add a new subsection to section 3.8.2, page 87 ("Shader Execution"): |
| 157 | |
| 158 | "Discard |
| 159 | |
| 160 | Fragment shaders may conditionally abandon operations using the discard |
| 161 | keyword. However, the ability of hardware to support abandoning operations |
| 162 | on a single sample when the shader is invoked once for each covered sample |
| 163 | is implementation-dependent. This capability can be determined by calling |
| 164 | GetBooleanv with the symbolic constant |
| 165 | FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT. If FALSE is returned, results from |
| 166 | shaders which discard based on per-sample logic are undefined." |
| 167 | |
| 168 | Changes to the OpenGL ES 2.0.24 Specification, Chapter 4 |
| 169 | |
| 170 | Replace first element of Figure 4.1, page 90 ("Fragment + Associated Data"): |
| 171 | |
| 172 | "Fragment (or sample) + Associated Data" |
| 173 | |
| 174 | New Implementation Dependent State |
| 175 | |
| 176 | Add to table 6.19 (Implementation Dependent Values (cont.)): |
| 177 | |
| 178 | Get Value Type Get Command Minimum Value Description Section |
| 179 | --------- ---- ----------- ------------- -------------- ------- |
| 180 | FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT B GetBooleanv - Samples may be 3.8.2 |
| 181 | discarded |
| 182 | individually |
| 183 | |
| 184 | Changes to the OpenGL ES Shading Language 1.0.17 Specification, Chapter 3 |
| 185 | |
| 186 | Remove Paragraph 2 of section 3.8, page 17, Identifiers ("Identifiers |
| 187 | starting with "gl_" are reserved [...]") and add: |
| 188 | |
| 189 | "Identifiers starting with "gl_" are reserved for use by OpenGL ES, and |
| 190 | may not be declared in a shader as either a variable or a function. |
| 191 | However, as noted in the specification, certain predeclared "gl_" names |
| 192 | are allowed to be redeclared in a shader for the specific purpose of |
| 193 | changing their precision qualifier." |
| 194 | |
| 195 | Changes to the OpenGL ES Shading Language 1.0.17 Specification, Chapter 7 |
| 196 | |
| 197 | Add after the last sentence of Paragraph 2 of Section 7.2, page 60, |
| 198 | Fragment Shader Special Variables ("These variables may be written to |
| 199 | more [...]"): |
| 200 | |
| 201 | "... To access the existing framebuffer values (e.g., to implement a |
| 202 | complex blend operation inside the shader), fragment shaders should use |
| 203 | the read-only input array gl_LastFragData. gl_LastFragData returns the |
| 204 | value written by the most recent fragment at the same position. |
| 205 | |
| 206 | Access to gl_LastFragData is optional, and must be enabled by |
| 207 | |
| 208 | #extension GL_EXT_shader_framebuffer_fetch : <behavior> |
| 209 | |
| 210 | Where <behavior> is as specified in section 3.3. |
| 211 | |
| 212 | By default, gl_LastFragData is declared with the mediump precision |
| 213 | qualifier. This can be changed by redeclaring the corresponding variables |
| 214 | with the desired precision qualifier. |
| 215 | |
| 216 | Redeclarations are done as follows |
| 217 | |
| 218 | // Redeclaration that changes nothing is allowed |
| 219 | mediump vec4 gl_LastFragData[gl_MaxDrawBuffers]; |
| 220 | |
| 221 | // All the following are allowed redeclaration that change behavior |
| 222 | lowp vec4 gl_LastFragData[gl_MaxDrawBuffers]; |
| 223 | highp vec4 gl_LastFragData[gl_MaxDrawBuffers]; |
| 224 | |
| 225 | Redeclarations must not otherwise alter the declared type or array size of |
| 226 | gl_LastFragData." |
| 227 | |
| 228 | Changes to the OpenGL ES Shading Language 3.00.3 Specification, Chapter 4 |
| 229 | |
| 230 | Modify Paragraph 2 of section 4.3.6: |
| 231 | "Except in the fragment stage, there is not an inout storage qualifier at |
| 232 | global scope for declaring a single variable name as both input and output |
| 233 | [...]" |
| 234 | |
| 235 | Modify Paragraph 5 of section 4.3.6: |
| 236 | "Fragment outputs output per-fragment data and are declared using the out |
| 237 | or inout storage qualifier. It is an error to use centroid out or centroid |
| 238 | inout in a fragment shader [...]" and append new paragraph: |
| 239 | |
| 240 | "Upon entry to the fragment shader, fragment outputs declared as inout will |
| 241 | contain the value written by the most recent fragment at the same position. |
| 242 | This behavior, and the ability to use the inout qualifier at global scope |
| 243 | in a fragment shader, is optional and must be enabled by |
| 244 | |
| 245 | #extension GL_EXT_shader_framebuffer_fetch : <behavior> |
| 246 | |
| 247 | Where <behavior> is as specified in section 3.4." |
| 248 | |
| 249 | Interactions with OES_standard_derivatives |
| 250 | |
| 251 | Results from shaders which use the built-in derivative functions dFdx, |
| 252 | dFdy, and fwidth on variables calculated using the current framebuffer |
| 253 | color are undefined. |
| 254 | |
| 255 | Revision History |
| 256 | |
| 257 | Version 4, 2013/05/28 - Added ES3 interaction as requested in Bug 10236 |
| 258 | Version 3, 2012/09/24 - Remove obsolete issue 3 about derivatives |
| 259 | Version 2, 2012/06/21 - Fix MULTISAMPLE enabled -> SAMPLE_BUFFERS = 1, |
| 260 | recast from APPLE to multivendor EXT, clarify that |
| 261 | gl_LastFragData reflects value written by previous |
| 262 | pixel at same coordinates. |
| 263 | Version 1, 2012/06/01 - Conversion from ARB_sync to APPLE_sync for ES. |