Name EXT_shader_pixel_local_storage2 Name Strings GL_EXT_shader_pixel_local_storage2 Contributors Jan-Harald Fredriksen, ARM Sandeep Kakarlapudi, ARM James Glanville, Imagination Technologies Tobias Hector, Imagination Technologies Contact Tobias Hector (tobias.hector 'at' imgtec.com) Status Complete Version Revision 0.13 Last Modified Date: October 28, 2015 Number OpenGL ES Extension #253 Dependencies OpenGL ES 3.0 and GLSL ES 3.0 are required. EXT_shader_pixel_local_storage is required. This extension has interactions with EXT_color_buffer_float and EXT_color_buffer_half_float This extension is written against the OpenGL ES Shading Language specification, Language Version 3.00, Document Revision 4 and revision OpenGL ES 3.0.2 of the API specification. Overview This extension builds on EXT_shader_pixel_local_storage by lifting the restriction that pixel local storage is not supported when rendering to multiple draw buffers. Moreover, pixel local storage values are no longer lost when writing to user-defined fragment outputs, and, correspondingly, framebuffer pixel values do not always become undefined when the shader writes to pixel local storage. This extension adds the following capabilities: - support for pixel local storage in combination with multiple user- defined fragment outputs - support for clearing pixel local storage variables - support for multi-word pixel local storage variables New Procedures and Functions void FramebufferPixelLocalStorageSizeEXT(uint target, sizei size); sizei GetFramebufferPixelLocalStorageSizeEXT(uint target); void ClearPixelLocalStorageuiEXT(sizei offset, sizei n, const uint *values); New Tokens Accepted by the parameters of GetBooleanv, GetIntegerv, GetInteger64v, or GetFloatv: MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_SIZE_EXT 0x9650 MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT 0x9651 Returned by CheckFramebufferStatus: FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_EXT 0x9652 New Macro Definitions #define GL_EXT_shader_pixel_local_storage2 1 New Built-in Variables None Changes to the OpenGL ES 3.0 Specification, Chapter 3 In Section 3.9.2, at the end of the last sub-section ("Shader Outputs"), modify the three paragraphs added by GL_EXT_shader_pixel_local_storage, such that it reads: "Fragment data values may also be written to pixel local storage blocks. These values are available for reading in subsequent shader invocations covering the same pixel. Data values written to pixel local storage block members are converted to the storage format specified in the shader. If GL_EXT_shader_pixel_local_storage2 is supported a shader may write to both user-defined fragment outputs and to pixel local storage blocks. If GL_EXT_shader_pixel_local_storage2 is not supported and a shader writes to any user-defined fragment output, the pixel local storage values for that fragment are lost, and their values in subsequent shader invocations are undefined. Similarly, if a shader writes to pixel local storage blocks, the value of the framebuffer pixel covered by that fragment becomes undefined." Changes to the OpenGL ES 3.0 Specification, Chapter 4 In Section 4.1.7 ("Blending"), modify the paragraph added by GL_EXT_shader- _pixel_local_storage to read: "Blending only applies to user-defined fragment outputs. No blending is performed for outputs to pixel local storage blocks. If the fragment shader outputs only to pixel local storage blocks, proceed to the next operation." In Section 4.1.9 ("Dithering), modify the paragraph added by GL_EXT_shader- _pixel_local_storage to read: "Dithering only applies to user-defined fragment outputs. No dithering is performed on outputs to pixel local storage blocks." In Section 4.2.3 ("Clearing the Buffers") add the following: "The command void ClearPixelLocalStorageuiEXT(sizei offset, sizei n, const uint *values); clears a consecutive region of the pixel local storage to a specified set of values. is the start offset of the region in 32-bit words. is the number of 32-bit words to clear. is an array of 32-bit words that specifies the values the pixel local storage should be cleared to. The words in are packed with the first component in the least significant bits of the word. The most significant bit of each component is packed in the most significant bit location of its location in the word. If is NULL, all pixel local storage in the supplied range has every bit set to 0. Clearing the pixel local storage will clear all values stored in the specified range. This will have the effect of making the value of any user- defined fragment output in this range undefined. Applications can determine the fragment output or pixel local storage variables the range corresponds to by the locations declared in the shader and by the storage sizes described in section 4.3.8.2 ("Output Layout Qualifiers") of the OpenGL ES Shading Language Specification. Further, an implementation is required to allocate variables in storage the following order: pixel local variables first, then fragment outputs. When ClearPixelLocalStorageuiEXT is called, no per-fragment operations or mask operations are applied. An INVALID_VALUE error will be generated if the sum of and exceeds the total amount pixel local storage available to a shader. An INVALID_OPERATION error will be generated if ClearPixelLocalStorageuiEXT is called while pixel local storage is disabled." Replace Section 4.4.3 ("Enabling pixel local storage") with the following: "4.4.3 Enabling pixel local storage Fragment shaders have access to pixel local storage blocks, but this access must be enabled prior to use and disabled after use. Pixel local storage for the current draw framebuffer is enabled by calling Enable with SHADER_PIXEL_LOCAL_STORAGE_EXT. The content of the pixel local storage for a pixel is initially undefined. The contents of the pixel local storage persist until color data is flushed to the framebuffer. After such an event, data in the pixel local storage is lost and the contents are undefined. Events that cause a flush include: * calling the GL commands Flush, Finish, and ClientWaitSync * calling commands such as TexSubImage2D, CopyTexSubImage2D, and BlitFramebuffer to update a texture that is also attached to the current draw framebuffer while pixel local storage is enabled * disabling pixel local storage by calling Disable with SHADER_PIXEL_- LOCAL_STORAGE_EXT. If pixel local storage is not enabled, an INVALID_OPERATION error will be generated if any rendering command is issued while a program object that accesses pixel local storage is bound. While pixel local storage is enabled, an INVALID_OPERATION error will be generated if any of the current draw framebuffer's attachment points are modified, including changes to the underlying storage backing of objects attached to these attachment points. An INVALID_OPERATION error will also be generated on attempts to bind a different framebuffer object, to delete the currently bound draw framebuffer, or change color buffer selection via DrawBuffers while pixel local storage is enabled. Pixel local storage is not supported in combination with multisample rasterization. Attempting to enable pixel local storage while the value of SAMPLE_BUFFERS is one will generate an INVALID_OPERATION error. An INVALID_FRAMEBUFFER_OPERATION error will be generated when attempting to enable pixel local storage while the current draw framebuffer is incomplete. The maximum number of bytes of pixel local storage available to a shader is specified by the value of the implementation-dependent constant MAX_- SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT. A compile-time error will be generated if an attempt is made to utilize more than the space available for pixel local storage variables. An implementation may choose to subdivide the amount of pixel local storage into a region for fast access and a region for normal access. As many pixel local storage variables as possible will be stored, in order of declaration, in the fast region before any variables will be allocated in the normal region. The number of bytes available for fast access is specified by the value of the implementation-dependent constant MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT. This value will always be less than or equal to the total amount of pixel local storage. The maximum number of bytes of combined storage per pixel available to a shader is specified by the value of the implementation-dependent constant MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT. This value is the combined storage of color attachments and pixel local storage. A compile-time error will be generated if an attempt is made to utilize more than the combined space for local storage. An INVALID_OPERATION error is generated by any command that draws geometry if the combined storage required for the current draw framebuffer and the pixel local storage of the current program is greater than this value. As for the total amount of pixel local storage, an implementation may choose to subdivide the amount of combined storage into a region for fast access and a region for normal access. The number of bytes available for fast access is specified by the value of the implementation-dependent constant MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_- SIZE_EXT. This value will always be less than or equal to the total amount of combined storage." Pixel local storage is disabled by calling Disable with SHADER_PIXEL_- LOCAL_STORAGE_EXT. In the initial state, SHADER_PIXEL_LOCAL_STORAGE_EXT is disabled. If EXT_shader_pixel_local_storage2 is to be used, then the amount of pixel local storage must be known to the framebuffer before pixel local storage is enabled, similar to a framebuffer attachment. The command void FramebufferPixelLocalStorageSizeEXT(uint target, sizei size); specifies the amount of storage required for pixel local variables whilst SHADER_PIXEL_LOCAL_STORAGE_EXT is enabled. specifies the framebuffer that is modified by this function. determines the size, in bytes, required for pixel local storage. An INVALID_VALUE error is generated if is greater than MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_- EXT, or if it is not a multiple of 4. An INVALID_OPERATION error is generated if an application tries to call this function whilst SHADER_- PIXEL_LOCAL_STORAGE_EXT is enabled. The amount of storage required for pixel local variables can be determined by the storage sizes described in section 4.3.8.2 ("Output Layout Qualifiers") of the OpenGL ES Shading Language Specification. If the default framebuffer is bound to , then calling this function does not affect framebuffer completeness. The command sizei GetFramebufferPixelLocalStorageSizeEXT(uint target); returns the size of pixel local storage previously set on the framebuffer bound to by FramebufferPixelLocalStorageSizeEXT." Add the following to the list of framebuffer complete conditions in sub-section "Whole Framebuffer Completeness" in section 4.4.4: " - The amount of pixel local storage specified by FramebufferPixelLocalStorageSizeEXT is zero, or the combined size of pixel local storage and fragment outputs is less than MAX_SHADER_- COMBINED_LOCAL_STORAGE_SIZE_EXT. { FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_EXT }" Add the following to the list of functions that can affect framebuffer completeness sub-section "Whole Framebuffer Completeness" in section 4.4.4: " - Changing the size of shader pixel local storage with FramebufferPixelLocalStorageSizeEXT." Errors Remove the following error added in EXT_shader_pixel_local_storage: INVALID_OPERATION is generated if the application attempts to enable pixel local storage while the current draw framebuffer is a user-defined frame- buffer object and has an image attached to any color attachment other than color attachment zero. Add the following errors: INVALID_VALUE is generated by ClearPixelLocalStorageuiEXT if the sum of and exceeds the total amount pixel local storage available to a shader. INVALID_OPERATION is generated if ClearPixelLocalStorageuiEXT is called while pixel local storage is disabled. INVALID_OPERATION is generated by any command that draws geometry if the combined storage required for the current draw framebuffer and the pixel local storage of the current program is is greater than the value of MAX_- SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT. New State Add to Table 6.13 Framebuffer (state per framebuffer object) State Type Get Command Initial Value Description Sec. --------------- ---- ------------ ------------- ----------- ----- Z+ GetFramebuffer- 0 Amount of pixel 4.4.3 PixelLocal- local storage StorageSizeEXT specified for the framebuffer. New Implementation Dependent State Add to Table 6.32 Implementation Dependent Fragment Shader Limits State Type Get Command Minimum Value Description Sec. --------------- ---- ------------ ------------- ----------- ----- MAX_SHADER_COMBINED- Z+ GetIntegerv 16 Amount of fast 4.4.3 LOCAL_STORAGE_FAST- storage in units _SIZE_EXT of bytes available for per-pixel storage. MAX_SHADER_COMBINED- Z+ GetIntegerv 16 Amount of total 4.4.3 LOCAL_STORAGE_SIZE- storage in units _EXT of bytes available for per-pixel storage. Additions to Chapter 4 ("Variables and Types") of the OpenGL ES Shading Language Specification Replace section "4.3.7 Pixel Local Variables" with the following: "4.3.7 Pixel Local Variables The __pixel_localEXT, __pixel_local_inEXT, and __pixel_local_outEXT, qualifiers are used to declare variables whose values are persistent across fragment shader invocations covering the same pixel, collectively referred to as pixel local variables. Pixel local variables do not have any backing store allocated through the OpenGL API and are not accessible to the API. Variables declared with the __pixel_localEXT qualifier can be read and written from the same fragment shader invocation. Variables declared with the __pixel_local_inEXT qualifier can only be read. Variables declared with the __pixel_local_outEXT qualifier can only be written. Pixel local storage variable reads and writes within a single shader invocation are processed in order. It is legal for a shader to write to both user-defined fragment outputs and pixel local storage variables. Pixel local storage variables may not have initializers and their contents are undefined until written to from a shader or initialized via the API. If a pixel local storage variable is not written to in a fragment shader, the value of that variable is undefined unless it was declared as part of a __pixel_localEXT block. Pixel local storage variables may be qualified with layout qualifiers affecting how the values are stored in and retrieved from the underlying storage, as described in section 4.3.8.4 "Pixel Local Block Layout Qualifiers". When reading from a pixel local storage variable, the in-storage value is implicitly converted from the storage format specified by the layout qualifier to the variable type. Similarly, when writing to a pixel local storage variable, the value of the member is implicitly converted to the storage format specified by the layout qualifier. Pixel local storage variables may only be declared inside interface blocks (section 4.3.7, "Interface Blocks"), which are then referred to as shader pixel local storage blocks. It is a compile-time error to declare pixel local storage variables at global scope (outside a block). Pixel local storage blocks must be declared at global scope. Pixel local storage variables declared inside pixel local storage blocks will be laid out in local storage in monotonically increasing order based on their location in the declaration. All pixel local variables consume integer multiples of 4 bytes, as specified in section 4.3.8.4. Pixel local storage blocks may be allocated from the same storage as any user-defined color outputs, but do not alias. Writing to pixel local variables has no effect on any user-defined outputs, and pixel local variables are not affected by writes to any user-defined outputs. A shader may only declare a single input and a single output pixel local storage block. A pixel local storage block declared using the __pixel_- localEXT qualifier is counted as both an input and an output block. Thus, it is a compile-time error for a shader to declare more than one pixel storage block, with the exception that it is legal to declare one pixel local storage block using the __pixel_local_inEXT qualifier and one with the __pixel_local_outEXT qualifier. Modify the start of Section 4.3.7 (Interface Blocks) to read: "Uniform and pixel local storage variable declarations can be grouped into named interface blocks to provide coarser granularity backing than is achievable with individual declarations. They can have an optional instance name, used in the shader to reference their members. A uniform block is backed by the application with a buffer object. A block of pixel local storage variables is not backed by any object. GLSL ES 3.0 does not support interface blocks for shader inputs or outputs. An interface block is started by a uniform or pixel local keyword, followed by a block name, followed by an open curly brace ( { ) as follows: interface-block: layout-qualifieropt interface-qualifier block-name { member-list } instance-nameopt; interface-qualifier: in out uniform __pixel_localEXT __pixel_local_inEXT __pixel_local_outEXT " Modify the sentence: "Repeating the uniform interface qualifier for a member's storage qualifier is optional." To read: "Repeating the uniform, __pixel_localEXT, __pixel_local_inEXT, or __pixel_local_outEXT interface qualifier for a member's storage qualifier is optional." Add a new paragraph after the one starting with: "For uniform blocks, the application uses the block name to identify the block." That reads: "For __pixel_localEXT, __pixel_local_inEXT, and __pixel_local_outEXT storage blocks, the block name is not used." In section 4.3.8.2, "Output Layout Qualifiers", add the following to the list of layout qualifiers applicable to fragment outputs only: layout-qualifier-id float-output-format-qualifier int-output-format-qualifier uint-output-format-qualifier generic-output-format-qualifier float-pixel-local-format-qualifier rgb565 r8 rg8 rgb8 rgba8 srgb8_a8 rgb5_a1 rgba4 rgb10_a2 [[ Only if EXT_color_buffer_float is supported ]] r32f rg32f r11f_g11f_b10f rgba32f [[ Only if EXT_color_buffer_half_float or EXT_color_buffer_float is supported ]] r16f rg16f rgba16f [[ Only if EXT_color_buffer_half_float is supported ]] rgb16f int-pixel-local-format-qualifier r8i r16i r32i rg8i rg16i rg32i rgba8i rgba16i rgba32i uint-pixel-local-format-qualifier r8ui r16ui r32ui rg8ui rg16ui rg32ui rgba8ui rgb10_a2ui rgba16ui rgba32ui generic-output-format-qualifier implementation_defined Add the following paragraphs to the end of this section: "The output format qualifiers are optional and must be enabled by calling #extension GL_EXT_shader_pixel_local_storage2: before use, where is as specified in section 3.4. Each output-format-qualifier specifies the format which each of the user-defined fragment outputs is stored at the end of shader execution. The values are packed to the specified format and stored as raw bits in fragment output storage. By default, the format for each output is set to "implementation_defined", and the underlying implementation will make a decision about how to store it. If any output is set to a format other than implementation_- defined, all formats must be specified. The output-format-qualifier format must match the base type and the number of components of the variable declaration. It is a compile-time error to declare a user-defined output variable where the format qualifier does not match the variable type and the number of components. If EXT_shader_pixel_local_storage2 is enabled, the format of every user-defined fragment output variable should be specified in order to use pixel local storage blocks. Any outputs set as implementation_defined (the default) behave as if consuming all available local storage, leaving no space for pixel local variables, causing a compile time error if pixel local storage blocks also exist in the shader. The specified output-format-qualifier does not need to be constant between shader invocations, but any resolves to the final framebuffer will treat the data as being of the format specified on the active frame- buffer's color attachment rather than the shader defined format. This implies that color attachment values are undefined if the format of the color attachment does not match the format specified in the shader. The number of user-defined outputs and the size specified by their format qualifier must remain consistent between shader invocations, or the values will be undefined. Each user-defined fragment output variable uses memory local to the shading processor. Each format takes up a predetermined number of bytes of storage, as specified in the table below. |----------------|-------| | Format | Bytes | |----------------|-------| | r8 | 4 | | r8ui | 4 | | r8i | 4 | | r16ui | 4 | | r16i | 4 | | r32ui | 4 | | r32i | 4 | | rg8 | 4 | | rg8ui | 4 | | rg8i | 4 | | rg16ui | 4 | | rg16i | 4 | | rg32ui | 8 | | rg32i | 8 | | rgb8 | 4 | | rgb565 | 4 | | rgba8 | 4 | | srgb8_a8 | 4 | | rgb5_a1 | 4 | | rgba4 | 4 | | rgb10_a2 | 4 | | rgba8ui | 4 | | rgba8i | 4 | | rgb10_a2ui | 4 | | rgba16ui | 8 | | rgba16i | 8 | | rgba32ui | 16 | | rgba32i | 16 | | r32f | 4 | | rg32f | 8 | | r11f_g11f_b10f | 4 | | rgba32f | 16 | | r16f | 4 | | rg16f | 4 | | rgb16f | 8 | | rgba16f | 8 | |----------------|-------| The total amount of memory used by a pixel local storage block or a user- defined fragment output can be determined by the size of each variable's format as in the equation below. n is the number of pixel local storage members or output variables in each case. n \¯ /_ i = sizeof(format-qualifier) i=0 The total combined amount of memory used by fragment outputs and pixel local storage can be worked out simply via the following: total memory = sizeof(pixel local storage) + sizeof(fragment outputs)" The total number of bytes of fragment output local storage available is specified by the value of the implementation-dependent constant gl_MaxShaderCombinedLocalStorageSizeEXT. A compile-time error will be generated if the declared outputs use more storage than this value. An implementation may choose to subdivide the amount of local storage into a region for fast access and a region for normal access. As many local variables as possible are allocated into the fast access region before any are allocated into the normal access. Pixel local variables are prioritized and are fully allocated into combined local storage before any fragment output variables are allocated. The number of total bytes available for fast access is specified by the value of the implementation- dependent constant gl_MaxShaderCombinedLocalStorageFastSizeEXT. This value will always be less than or equal to the total amount of combined local storage." In Section 4.3.8.4 ("Pixel Local Block Layout Qualifiers"), add the following (add the following to the list of layout qualifiers for pixel local storage variables) float-pixel-local-format-qualifier rg32f rgba32f rgba16f int-pixel-local-format-qualifier rgba16i r32i rg32i rgba32i uint-pixel-local-format-qualifier rg32ui rgba16ui rgba32ui (add to the end of the description of the pixel local block layout qualifiers) "The size of each pixel local format qualifier is equivalent to that specified for the output format qualifiers in section 4.3.8.2." Additions to Chapter 6 of the OpenGL ES Shading Language Specification In Section 6.4 (Jumps), change the sentence about the discard keyword that currently reads: 'This keyword causes the fragment to be discarded and no updates to the framebuffer will occur.' to: 'This keyword causes the fragment to be discarded and no updates to the framebuffer or any pixel local storage variables will occur.' Additions to Chapter 7 of the OpenGL ES Shading Language Specification In Section 7.3 (Built-In Constants), add new entries: const mediump int gl_MaxShaderCombinedLocalStorageFastSizeEXT = 16 const mediump int gl_MaxShaderCombinedLocalStorageSizeEXT = 16 Examples (1) G-buffer creation pass #version 300 es #extension GL_EXT_shader_pixel_local_storage2 : enable varying vec2 coord; varying vec3 normal; uniform sampler2D albedo_metallicness_texture; uniform sampler2D roughness_texture; uniform float roughness; uniform float albedo; uniform vec3 metallicness; __pixel_localEXT FragDataLocal { layout (r32f) highp float depth; layout (rgba8ui) highp vec4 normal_roughness; layout (rgba8ui) highp vec4 albedo_metallicness; } gbuf; void main() { // Write to pls values gbuf.depth = gl_FragCoord.z; gbuf.normal_roughness = vec4(normal, texture2d(roughness_texture).r); gbuf.albedo_metallicness = texture2d(albedo_metallicness_texture, coord); } (2) Light accumulation step (multiple lights can hit the same pixel) #version 300 es #extension GL_EXT_shader_pixel_local_storage2 : enable uniform vec4 light_position; __pixel_localEXT FragDataLocal { layout (r32f) highp float depth; layout (rgba8ui) highp vec4 normal_roughness; layout (rgba8ui) highp vec4 albedo_metallicness; } gbuf; layout(location = 0, rgba10_a2) out highp vec4 accumulationBuffer; void main() { // Accumulate to the accumulationBuffer, without invalidating the pls data accumulationBuffer = do_lighting(gbuf.depth, gbuf.normal_roughness, gbuf.albedo_metallicness, light_position); } Issues (1) Should there be a way to dumping the PLS contents to memory for debugging purposes? RESOLVED: Not in this extension. A couple of ways this could be supported: A) Reuse ReadPixels. Allow a new combination of and parameters, say, "SHADER_PIXEL_LOCAL_STORAGE" and UNSIGNED_INT. B) Add a new function, say glReadPixelLocalStorage. This would be as the above, except that the and parameters would be implicit. Either approach would probably need a query function to determine the amount of storage used, or a way to specify the amount of storage to retrieve. (2) How are local storage values initialized? RESOLVED: Using ClearPixelLocalStorageuiEXT. EXT_shader_pixel_local_storage stated: "All pixel local storage variables are guaranteed to be zero if all color components of the framebuffer are set to zero." But with this extension, color data and pixel local storage are distinct, so while this guarantee could be made, it may not be the most efficient approach. This is solved by adding an explicit API: ClearPixelLocalStorageuiEXT. (3) Is the proposed resolution to (2) a compatibility break with EXT_- shader_pixel_local_storage? RESOLVED: No. EXT_shader_pixel_local_storage guaranteed that the pixel local storage was initialized to zero if all color components of the framebuffer were set to zero. Given that this only applied to the aliased pixel local storage in the original extension, and aliasing is no longer present, the resolution is not a compatibility break, as the spec itself is a compatibility break. (4) Do we need to know the render target count at compile time? RESOLVED. Yes. Implementations will need to know the render target count and the storage size of each render target in order to allocate and partition the pixel local storage. (5) Do we want to explicitly alias some pixel local storage variables onto color rendertargets? RESOLVED. See Issue 7. (6) Should the maximum PLS storage queries be per framebuffer? RESOLVED: No - glGetInteger with a MAX_COMBINED_LOCAL_STORAGE_SIZE. Dynamic, per framebuffer, queries will have all necessary information, but applications can not access this information until the framebuffer object has been created, which seems undesirable. EXT_shader_pixel_local_storage specified static queries for the amount of available pixel local storage. With this extension, the semantics of that query changes since color and pixel local storage no longer alias. Given that change, we need a query for the total amount of storage available for pixel local storage and color attachments. (7) Do we want to keep the aliasing of pixel local storage variables onto color rendertargets? RESOLVED: No The main benefit of aliasing was that it potentially allows more (fast) local storage. Instead of sharing the local storage between color render targets and pixel local storage variables, all local storage can be allocated to pixel local storage initially. In this case, we expect all pixel local storage to be resolved (and become undefined) when any user-defined color output is written to (and vice versa). However, given the existance (and support) of framebuffer fetch, it seems unnecessary to continue using this - the same effect can be achieved with side-by-side framebuffer fetch and pixel local storage, without the drawback of requiring explicit resolves. (8) Do we want the full range of framebuffer formats to work with this extension? If so, how do we define the sizes of, say rgb565? Does it take up 16bits or is it assumed to be padded to 32 bits? RESOLVED: Add all formats, but storage for all formats is padded to multiples of 32-bits. (9) Do the usual per-fragment operations apply to color outputs in this extension? RESOLVED: Yes. All values written to user-defined color outputs pass through per-fragment operations (including blending, alpha to coverage, etc.) as normal. Revision History Revision 0.13, 28/10/2015 (Tobias Hector) Added enumerant values Revision 0.12, 08/10/2015 (Tobias Hector) Added PLS interactions with the discard keyword. Revision 0.11, 07/10/2015 (Tobias Hector) Specified that PLS variables are undefined if they're not written to, unless they were defined as both input and output (in which case they are preserved). Revision 0.10, 13/07/2015 (Tobias Hector) Re-added error about multisampled rendering Revision 0.9, 10/07/2015 (Tobias Hector) Corrected ClearPixelLocalStorageuiEXT to accept a uint value, instead of int Changed language about combined local storage to be clearer. Revision 0.8, 03/07/2015 (Tobias Hector) Added wording that disallows the default framebuffer becoming incomplete. Added language allowing NULL to be passed into ClearPixelLocalStorageuiEXT Added word alignment to size parameter of FramebufferPixelLocalStorageSizeEXT Revision 0.7, 02/07/2015 (Tobias Hector) Folded in updates from external review. Added interactions with EXT_color_buffer_float and half_float Added multi-word pixel local storage formats Added framebuffer pixel local storage size specification Added framebuffer completeness checks Updated issues list to match updated spec. Revision 0.6, 03/10/2014 (Jan-Harald Fredriksen) Extended padding for all color outputs to 4 bytes. Resolved and updated proposed resolutions for several issues. Added Issue 10 and Issue 11. Revision 0.5, 25/09/2014 (Jan-Harald Fredriksen) Integrated a subset of IMG_fragment_output_format. Revision 0.4, 20/06/2014 (Jan-Harald Fredriksen) Minor wording changes. Revision 0.3, 27/05/2014 (Jan-Harald Fredriksen) Adding Issue 7. Revision 0.2, 18/05/2014 (Jan-Harald Fredriksen) Adding some issues and a new query. Revision 0.1, 21/03/2014 (Jan-Harald Fredriksen) Second internal draft. Adding missing changes compared to EXT_shader_pixel_local_storage. Added proposed resolution of Issue 1. Added Issue 2, Issue 3, and Issue 4. Revision 0, 19/11/2013 (Jan-Harald Fredriksen) First internal draft.