EXT_shader_pixel_local_storage2

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 <pname> 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. <offset> is the start offset of the region in 32-bit words. <n>
 is the number of 32-bit words to clear. <values> is an array of <n> 32-bit
 words that specifies the values the pixel local storage should be cleared
 to. The words in <n> 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
 <values> 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 <offset> and <n>
 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. <target> specifies the
 framebuffer that is modified by this function. <size> determines the size,
 in bytes, required for pixel local storage. An INVALID_VALUE error is
 generated if <size> 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 <target>, 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 <target> 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
<offset> and <n> 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: <behavior>

  before use, where <behavior> 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_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 <format> and <type>
        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 <format> and <type> 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.