Name

    EXT_shader_pixel_local_storage

Name Strings

    GL_EXT_shader_pixel_local_storage

Contributors

    Jan-Harald Fredriksen, ARM
    Sandeep Kakarlapudi, ARM
    Marius Bjorge, ARM
    Alexander Galazin, ARM
    Tobias Hector, Imagination Technologies
    Ilya Zaytsev, ARM

Contact

    Jan-Harald Fredriksen (jan-harald.fredriksen 'at' arm.com)

Status

    Shipping.

Version

    Revision 6
    Last Modified Date: Mar 12, 2014

Number

    OpenGL ES Extension #167

Dependencies

    OpenGL ES 3.0 is required.

    This extension is written against the OpenGL ES Shading Language
    specification, Language Version 3.00, Document Revision 3 and revision
    OpenGL ES 3.0 of the API specification.

Overview

    Techniques such as deferred shading and deferred lighting are often
    implemented by attaching multiple color render targets to a framebuffer
    object, rendering the required intermediate data, and then sampling from
    this data as textures.  While flexible, this approach consumes a large
    amount of external memory bandwidth, which is at a premium on mobile
    devices.

    Observing that the intermediate or "G-buffer" data is often only written to
    and read by shaders executing for the same pixel position, tile-based
    renderers can offer a more efficient alternative by keeping the data on-GPU.
    This allows large amounts of data to be kept per-pixel, with zero external
    memory bandwidth impact.

    This extension provides a way for applications to pass information between
    fragment shader invocations covering the same pixel by introducing the
    concept of pixel local storage. Pixel local storage is an on-chip memory
    storage that can be efficiently accessed by fragments being processed by
    the GL. The format of data stored in the pixel local storage is independent
    of the format of the currently attached framebuffer. The data in pixel local
    storage is not written back to main memory. Access to pixel local storage
    is controlled via glEnable and glDisable. If commands that implicitly or
    explicitly flush the GL command stream are issued when pixel local storage
    is enabled then the contents of the pixel local storage becomes undefined
    for subsequent commands.

New Procedures and Functions

    None

New Tokens

    Accepted by the <pname> parameters of GetBooleanv, GetIntegerv,
    GetInteger64v, or GetFloatv:

        MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT 0x8F63
        MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT      0x8F67

    Accepted by the <pname> parameters of IsEnabled, GetBooleanv, GetIntegerv,
    GetInteger64v, or GetFloatv:

        SHADER_PIXEL_LOCAL_STORAGE_EXT               0x8F64

New Macro Definitions

    #define GL_EXT_shader_pixel_local_storage 1

Additions to Chapter 4 of the OpenGL ES Shading Language Specification

    In Section 4.3 (Storage Qualifiers), add a qualifiers to the table:

    "Qualifier            Meaning
     --------             -------
     __pixel_localEXT     fragment shader only; storage can be read and written
                          and is persistent across shader invocations covering
                          the same pixel

     __pixel_local_inEXT  fragment shader only; storage can be read and is
                          persistent across shader invocations covering the same
                          pixel; storage can be written in another shader
                          invocation declaring __pixel_localEXT or __pixel_-
                          local_outEXT storage.

     __pixel_local_outEXT fragment shader only; storage can be written and is
                          persistent across shader invocations covering the same
                          pixel; storage is read in another shader invocation
                          declaring __pixel_localEXT or __pixel_local_inEXT
                          storage.
    "

    Then add a new paragraph at the end of the section:
    "The __pixel_localEXT, __pixel_local_inEXT, and __pixel_local_outEXT
     qualifiers are optional and must be enabled by calling

      #extension GL_EXT_shader_pixel_local_storage : <behavior>

     before use, where <behavior> is as specified in section 3.4."

    After Section 4.3.6 (Output Variables), add a new paragraph:

    "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 storage variables. Pixel local storage 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 and __pixel_local_outEXT qualifiers can only be read
    and written, respectively.

    Pixel local storage variable reads and writes within a single shader
    invocation are processed in order.

    It is a compile-time error for a shader to statically write to both regular
    user-defined fragment outputs and to pixel local storage variables. Reading
    from pixel local storage variables and writing to user-defined fragment
    outputs is, however, legal.

    Pixel local storage variables may not have initializers and their contents
    are undefined until written to from a shader.

    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 storage
    variables consume exactly 4 bytes of storage.

    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."

    Modify the first paragraph of 4.3.8 (Layout Qualifiers) to read:

    "Layout qualifiers can appear in several forms of declaration. They can
     appear as part of an interface block definition or block member, as shown
     in the grammar in the previous section. They can also appear with just an
     interface qualifier (a storage qualifier that is in, out, uniform,
     __pixel_localEXT, __pixel_local_inEXT, or __pixel_local_outEXT) to
     establish layouts of other declarations made with that interface qualifier:

     layout-qualifier interface-qualifier ;
    "

    Then remove paragraph starting with "Interface qualifiers are a subset of
    storage qualifiers:" and the subsequent grammar for the interface-qualifier.
    This is now described in section 4.3.7.

    Add a new paragraph:
    "
    4.3.8.4 Pixel Local Block Layout Qualifiers

    Layout qualifiers can be used for pixel local storage variables. The layout
    qualifier identifiers for pixel local storage variables are:

    layout-qualifier-id
        float-pixel-local-format-qualifier
        int-pixel-local-format-qualifier
        uint-pixel-local-format-qualifier

    float-pixel-local-format-qualifier
        r11f_g11f_b10f
        r32f
        rg16f
        rgb10_a2
        rgba8
        rg16
    int-pixel-local-format-qualifier
        rgba8i
        rg16i
    uint-pixel-local-format-qualifier
        rgb10_a2ui
        rgba8ui
        rg16ui
        r32ui

    None of these have any semantic affect at all on the usage of the variables
    being declared; they only describe how data is laid out in the underlying
    storage.

    The component format must match the base type and the number of components
    of member declarations. It is a compile-time error to declare a pixel local
    member where the format qualifier does not match the member type and the
    number of components.

    Pixel local storage layout qualifiers can be declared for global scope, on
    a single pixel local storage block, or on a single pixel local storage block
    member declaration.

    Default layouts are established at global scope for pixel local storage
    blocks as

        layout(layout-qualifier-id-list) __pixel_localEXT;
        layout(layout-qualifier-id-list) __pixel_local_inEXT;
        layout(layout-qualifier-id-list) __pixel_local_outEXT;

    The initial state of compilation is as if the following were declared:

        layout(r32ui) __pixel_localEXT;
        layout(r32ui) __pixel_local_inEXT;
        layout(r32ui) __pixel_local_outEXT;

    Pixel local storage blocks can be declared with optional layout qualifiers,
    and so can their individual member declarations. Such block layout
    qualification is scoped only to the content of the block. As with global
    layout declarations, block layout qualification first inherits from
    the current default qualification and then overrides it. Similarly,
    individual member layout qualification is scoped just to the member
    declaration, and inherits from and overrides the block's qualification.

    The float-pixel-local-format-qualifier, the int-pixel-local-format-
    qualifier, and the uint-pixel-local-format-qualifier overrides any previous
    any previous use of any of these qualifiers; other qualifiers are inherited.

    When multiple arguments are listed in a layout declaration, the effect will
    be the same as if they were declared one at a time, in order from left to
    right, each in turn inheriting from and overriding the result from the
    previous qualification.

    Example with per-member qualifiers:

    __pixel_localEXT FragDataLocal {
        layout(r11f_g11f_b10f) mediump vec3 normal;
        layout(rgb10_a2ui) mediump uvec4 color;
        layout(r32ui) highp uint flags;
    };

    Example with inherited qualifiers:

    layout(rgba8ui) __pixel_localEXT FragDataLocal {
        layout(rgb10_a2, r11f_g11f_b10f) mediump vec3 normal; // storage is r11f_g11f_b10f
        layout(rgb10_a2ui) mediump uvec4 color;
        mediump uvec4 flags;                                  // storage is rgba8ui
    };

    Example of invalid local block declaration:

    layout(rgba8ui) __pixel_localEXT FragDataLocal {
        layout(r11f_g11f_b10f) mediump float normal;          // error, component counts must match
        layout(rgb10_a2ui) mediump vec4 color;                // error, base types must match
    };
    "

Additions to Chapter 7 of the OpenGL ES Shading Language Specification

    In Section 7.3 (Built-In Constants), add a new entry:

    const mediump int gl_MaxShaderPixelLocalStorageFastSizeEXT = 16
    const mediump int gl_MaxShaderPixelLocalStorageSizeEXT = 16

Changes to the OpenGL ES 3.0 Specification, Chapter 3

    In Section 3.9, at the end of the last sub-section ("Shader Outputs") add:

    "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 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"), add after the fourth paragraph ("Blending
    applies only if ..."):

    "Blending only applies for user-defined fragment outputs. If the fragment
     shader outputs to pixel local storage blocks, proceed to the next
     operation."

    In Section 4.1.9 ("Dithering), add after the second paragraph ("Many
    dithering selection ..."):

    "If the fragment shader outputs to pixel local storage blocks, no dithering
     is performed."

    In Section 4.4 ("Framebuffer Objects") modify the sentence:

    "In particular, a framebuffer object encapsulates state necessary to
     describe a collection of color, depth, and stencil logical buffers (other
     types of buffers are not allowed)."

    to read:
    "In particular, a framebuffer object encapsulates state necessary to
     describe a collection of color, depth, and stencil logical buffers (other
     types of buffers cannot be attached)."

    Then add the following paragraph to the end of the Section (before 4.4.1):

    "A set of pixel local storage values may also be associated with the
     framebuffer. These values are not backed by any framebuffer-attachable
     image. This allows the GL to pass information between fragment shader
     invocations covering the same pixel without requiring an attached object
     to provide the underlying storage backing. The pixel local storage is only
     valid while it is enabled as described in section 4.4.3."

    Add a new section after 4.4.2 "Attaching Images to Framebuffer Objects" and
    increase the section number for the the following subsections:

    "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 contents of the pixel local storage for a pixel are initially an
    implementation-defined function of the current value of the pixel in the
    framebuffer. All pixel local storage variables are guaranteed to be zero if
    all color components of the framebuffer are set to zero.

    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.

    Pixel local storage is not supported when rendering to multiple draw
    buffers. Attempting to enable pixel local storage while the current draw
    framebuffer is a user-defined framebuffer and has an image attached to any
    color attachment other than color attachment zero will generate an INVALID_-
    OPERATION error. Similarly, attempting to enable pixel local storage while
    the draw buffer for any color output other than color output zero is not
    NONE 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 total 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.

    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.
   "

Errors

    INVALID_OPERATION is generated if the application attempts enable pixel
    local storage while the value of SAMPLE_BUFFERS is one.


    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.

    INVALID_OPERATION is generated if the application attempts to enable pixel
    local storage while the current draw framebuffer is a user-defined frame-
    buffer and the draw buffer for any color output other than color
    output zero is not NONE.

    INVALID_FRAMEBUFFER_OPERATION is generated if the application attempts to
    enable pixel local storage while the current draw framebuffer is incomplete.

    INVALID_OPERATION is generated if pixel local storage is disabled and the
    application attempts to issue a rendering command while a program object
    that accesses pixel local storage is bound.

    INVALID_OPERATION is generated if pixel local storage is enabled and the
    application attempts to bind a new draw framebuffer, delete the currently
    bound draw framebuffer, change color buffer selection via DrawBuffers, or
    modify any attachment of the currently bound draw framebuffer including
    their underlying storage.

New State

    Add to Table 6.12 Framebuffer Control

    Get Value           Type Get Command  Initial Value Description       Sec.
    ---------------     ---- ------------ ------------- -----------       -----
    SHADER_PIXEL_LOCAL- B    IsEnabled    FALSE         Pixel local       4.4.3
    STORAGE_EXT                                         storage.

New Implementation Dependent State

    Add to Table 6.32 Implementation Dependent Fragment Shader Limits

    State               Type Get Command  Minimum Value Description       Sec.
    ---------------     ---- ------------ ------------- -----------       -----
    MAX_SHADER_PIXEL-   Z+   GetIntegerv  16            Amount of fast    4.4.3
    LOCAL_STORAGE_FAST-                                 storage in units
    _SIZE_EXT                                           of bytes available
                                                        for pixel local
                                                        storage variables.

    MAX_SHADER_-        Z+   GetIntegerv  16            Amount of total   4.4.3
    PIXEL_LOCAL_STORAGE-                                storage in units
    _SIZE_EXT                                           of bytes available
                                                        for pixel local
                                                        storage variables.

Examples

    (1) Use the extension to write data.

    #version 300 es
    #extension GL_EXT_shader_pixel_local_storage : enable

    __pixel_localEXT FragDataLocal {
        layout(r11f_g11f_b10f) mediump vec3 normal;
        layout(rgb10_a2) highp vec4 color;
        layout(rgba8ui) mediump uvec4 flags;
    } gbuf;

    void main()
    {
        /* .... */
        gbuf.normal = v;
        gbuf.color = texture(sampler, coord);
        gbuf.flags = material_id;
    }

    (2) Use the extension to resolve the data.

    #version 300 es
    #extension GL_EXT_shader_pixel_local_storage : enable

    __pixel_localEXT FragDataLocal {
        layout(r11f_g11f_b10f) mediump vec3 normal;
        layout(rgb10_a2) highp vec4 color;
        layout(rgba8ui) mediump uvec4 flags;
    } gbuf;

    out highp vec4 fragColor;

    void main()
    {
        fragColor = do_lighting(gbuf.normal, gbuf.color, gbuf.flags, light_pos);
    }

Issues

    (1) Should errors be raised when this extension is used in combination with
        blending and dithering?

        RESOLVED.

        No. Blending and dithering should be ignored when the shader outputs raw
        values.

    (2) Should errors be raised when this extension is used in combination with
        multisampling?

        RESOLVED.

        Yes. This can be trivially detected when the pixel local storage is
        enabled.

        The alternative is that it results in undefined results. As long as the
        shader is only run once per fragment, this should sort of work except
        the coverage mask could mask out some bits.

    (3) Should explicit packing functions be supported?

        RESOLVED.

        No.

        Early versions of this extensions required explicit packing functions
        to be used when writing to and reading from the pixel local storage.
        This version of the extension does implicit conversions in  of these
        cases so packing functions are not required.

    (4) What is the initial values of local variables?

        RESOLVED.

        On a cleared framebuffer, the values of pixel local variables will be
        some function of the clear color value. But the function may be
        different depending on the format of the framebuffer. This makes the
        value effectively undefined unless the framebuffer has been cleared to
        zero.

        See also Issue 5.

    (5) Do we need an API to initialize the pixel local variables?

        RESOLVED.

        No. This is deferred to a future extension.

        Given Issue 4, there is no convenient way to initialize these variables
        to anything other than zero.

        Applications can initialize it by drawing a fullscreen quad that writes
        to the local outputs, but that may not be the most efficient way.

        An alternative solution is to define a new API to clear the framebuffer
        along the lines of:
            ClearLocaluiEXT(enum buffer, uint n, const T *values);

    (6) Should the raw storage alias the fragment color?

        RESOLVED.

        Applications may want to mix shaders using pixel local storage and user-
        defined outputs. This could be supported if we reserve a number of bits
        (where the number depends on the framebuffer format) for the user-
        defined outputs.

        This approach may make it possible to support this functionality on
        non-tile based renderers by directing raw values to a separate buffer
        in memory.

        This extension currently aliases the storage. Applications can manually
        preserve the framebuffer value by using ARM_shader_framebuffer_fetch,
        EXT_shader_framebuffer_fetch, or similar extensions to retrieve the
        color value and then store this as a local value.

    (7) Is there a way to salvage some aspect of multisampling?

        RESOLVED.

        Multisampling is clearly a desirable feature. The most likely
        implementation of this extension, however, is to reuse the pixel local
        storage normally used for multisample data to store application-specific
        data, thus making this extension incompatible with multisampled
        rasterization.

        Support for multisampling is left to a future extension.

    (8) Should pixel local variables be allowed declared outside interface
        blocks?

        RESOLVED.

        No. This makes the pixel local storage much more difficult to manage.
        The ESSL compiler would have to enforce ordering rules  shaders to make
        sure that all shaders see the pixel local storage declarations in the
        same order. This seems to add implementation complexity for no obvious
        benefit.

    (9) Should packUnitVector3 be added in a separate extension?

        RESOLVED.

        Extended packing functions is only indirectly related to the core
        feature exposed by this extension. They could potentially have other
        use-cases. This could be added in the future if needed. See Issue 15.

    (10) What happens to the local storage after eglSwapBuffers?

        RESOLVED.

        The contents of the pixel local storage are lost after a call to
        eglSwapBuffers. In this respect, pixel local storage acts as an
        ancillary buffer than cannot be preserved.

     (11) Can pixel local storage variables be arrays?

        RESOLVED.

        Yes. There's no reason not to support this.

     (12) Are variables declared with the pixel local qualifiers preserved?

        RESOLVED.

        There are two options: A) the implementation implicitly preserves all
        unwritten pixel local variables, and B) the shader must explicitly
        preserve unwritten pixel local variables.

        Consider the following local storage block:
           __pixel_localEXT FragDataLocal {
              layout(r11f_g11f_b10f) mediump vec3 normal;
              layout(rgb10_a2) highp vec4 color;
              layout(rgba8ui) mediump uvec4 flags;
           } gbuf;
        If a shader only writes to 'color', option B would make 'normal and
        'flags' undefined unless the shader also manually assigned these
        variables to themselves. This would certainly be unexpected. If a
        shader wants to reduce the data, e.g., by only preserving the 'normal'
        variable, it can do so by declaring separate __pixel_local_inEXT and
        __pixel_local_outEXT blocks.

        Option A is chosen.

     (13) Can CopyTex[Sub]Image, ReadPixels, and BlitFramebuffer be called
          while pixel local storage is enabled?

        RESOLVED.

        These calls are all supported, but may not be very useful.

        For CopyTex[Sub]Image and ReadPixels, the contents of the color buffer
        will have undefined contents if the pixel local storage variables have
        not yet been resolved.

        BlitFramebuffer implicitly writes to the color buffer of the draw
        framebuffer and will thus make all pixel local storage variables
        associated with it undefined.

     (14) What does 'undefined' mean for a pixel local storage variable
          or a color value?

        RESOLVED.

        It simply means that the value has no well-defined meaning to an
        application. It does _not_ mean that the value is random nor that it
        could have been leaked from other contexts or processes.

     (15) Do we need a built-in function to pack unit vectors?

        RESOLVED.

        No, there is no need for this.

        Earlier drafts of this extensions added ESSL built-in functions to pack
        and unpack unit vectors (packUnitVector3EXT, unpackUnitVector3EXT).
        These would, however, only be useful if they gave performance
        improvements over plain ESSL code, which they do not.

        The following packing functions have been found to generate equivalent
        code to the proposed built-in functions:

        highp uint packUnitVector3(mediump vec3 n)
        {
           highp float p = sqrt(2.0) * sqrt(n.z + 1.0);
           return packHalf2x16(n.xy / p);
        }

        mediump vec3 unpackUnitVector3(highp uint p)
        {
           highp vec2 fenc = unpackHalf2x16(p);
           highp float f = dot(fenc, fenc);
           highp float g = sqrt(1.0 - f);
           highp vec3 n;
           n.xy = 2.0*fenc*g;
           n.z = 1.0 - 2.0*f;
           return n;
        }

     (16) When writing to a single output value in a shader, do all local
          storage values become invalid immediately? And vice versa?

        E.g:
        fragmentOutputValue  = localstorage.value;
        // Does a further access return an undefined value?
        fragmentOutputValue += localstorage.value;

        RESOLVED: No, these variables retain their values for the life of the
                  shader.

        Fragment outputs and local storage variables are treated as temporary
        variables during execution of a shader, rather than accessing the
        underlying storage directly. Final values are only written to underlying
        storage at the end of a shader's execution. Within a shader instance,
        these variables can be read or written safely in any order.

Revision History

    Revision 6, 12/03/2014 (Jan-Harald Fredriksen)
        Added Issue 16.

    Revision 5, 18/02/2014 (Jan-Harald Fredriksen)
        Clarified that pixel local storage is undefined after flush commands.
        Updated error conditions for MRT to cover the default framebuffer.
        Minor wording changes.
        Resolved Issue 7.
        Expanded Issue 15.
        Updated resolution of Issue 3.

    Revision 4, 22/12/2013 (Jan-Harald Fredriksen)
        Changed name to EXT_shader_pixel_local_storage.
        Added MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT.
        Clarified memory layouts within local storage blocks.

    Revision 3, 14/10/2013 (Jan-Harald Fredriksen)
        Fixed a typo.
        Modified error conditions with multiple draw buffers.

    Revision 2, 27/09/2013 (Jan-Harald Fredriksen)
        Increased minimum maximum storage to 16 bytes.
        Fixed a couple of typos.
        Added Issues 13 and 14.
        Added an error condition when enabling pixel local storage on an
        incomplete FBO.
        Restricted local storage to color attachment zero.
        Disallowed changing buffer selection DrawBuffers while pixel local
        storage is enabled.
        Removed packUnitVector3/unpackUnitVector3 and added Issue 15.

    Revision 1, 29/07/2013 (Jan-Harald Fredriksen)
        First external draft.
