Name

    EXT_shader_implicit_conversions

Name Strings

    GL_EXT_shader_implicit_conversions

Contact

    Jon Leech (oddhack 'at' sonic.net)
    Daniel Koch, NVIDIA (dkoch 'at' nvidia.com)

Contributors

    Slawomir Grajewski, Intel
    Contributors to ARB_gpu_shader5

Notice

    Copyright (c) 2010-2013 The Khronos Group Inc. Copyright terms at
        http://www.khronos.org/registry/speccopyright.html

    Portions Copyright (c) 2013-2014 NVIDIA Corporation.

Status

    Complete.

Version

    Last Modified Date: April 1, 2014
    Revision: 6

Number

    OpenGL ES Extension #179

Dependencies

    OpenGL ES 3.1 and OpenGL ES Shading Language 3.10 are required.

    This specification is written against the OpenGL ES 3.10 Shading
    Language (March 17, 2014) Specification.

Overview

    This extension provides support for implicitly converting signed integer
    types to unsigned types, as well as more general implicit conversion and
    function overloading infrastructure to support new data types introduced by
    other extensions.

Modifications to The OpenGL ES Shading Language Specification, Version 3.10

    Including the following line in a shader can be used to control the
    language features described in this extension:

      #extension GL_EXT_shader_implicit_conversions : <behavior>

    where <behavior> is as specified in section 3.4.

    A new preprocessor #define is added to the OpenGL ES Shading Language:

      #define GL_EXT_shader_implicit_conversions        1


    Add new section 4.1.10 following section 4.1.9 "Arrays":

    4.1.10 Implicit Conversions

    In some situations, an expression and its type will be implicitly
    converted to a different type. The following table shows all allowed
    implicit conversions:

                                Can be implicitly
        Type of expression        converted to
        ---------------------   -----------------
        int                     uint, float
        ivec2                   uvec2, vec2
        ivec3                   uvec3, vec3
        ivec4                   uvec4, vec4
        uint                    float
        uvec2                   vec2
        uvec3                   vec3
        uvec4                   vec4

    No implicit conversions are provided to convert from unsigned to signed
    integer types or from floating-point to integer types. There are no
    implicit array or structure conversions.

    When an implicit conversion is done, it is not a re-interpretation of
    the expression's bit pattern, but a conversion of its value to an
    equivalent value in the new type. For example, the integer value -5 will
    be converted to the floating-point value -5.0. Integer values having
    more bits of precision than a single-precision floating-point mantissa
    will lose precision when converted to float.

    When performing implicit conversion for binary operators, there may be
    multiple data types to which the two operands can be converted. For
    example, when adding an int value to a uint value, both values can be
    implicitly converted to uint and float. In such cases, a floating-point
    type is chosen if either operand has a floating-point type. Otherwise,
    an unsigned integer type is chosen if either operand has an unsigned
    integer type. Otherwise, a signed integer type is chosen. If operands
    can be implicitly converted to multiple data types deriving from the
    same base data type, the type with the smallest component size is used.
    The conversions in the table above are done only as indicated by other
    sections of this specification.


    Modify Section 5.9 "Expressions", p. 81:

    (modify the specified items in the bulleted list as follows, adding
    support for implicit conversion between signed and unsigned types)

    Expressions in the shading language are built from the following:

    * The arithmetic binary operators add (+), subtract (-), multiply (*),
      and divide (/) operate on integer an floating-point scalars, vectors,
      and matrices. If the fundamental types in the operands do not match,
      then the conversions from section 4.1.10 "Implicit Conversions" are
      applied to create matching types. All arithmetic binary operators ...

    * The operator modulus (%) operates on signed or unsigned integer
      scalars or integer vectors. If the fundamental types of the operands
      do not match, the conversions from Section &4.1.10 "Implicit
      Conversions" are applied to produce matching types. The operands
      cannot be vectors of differing size ...

    * The relational operators greater than (>), less than (<), greater than
      or equal (>=), and less than or equal (<=) operate only on scalar
      integer and scalar floating-point expressions. The result is scalar
      Boolean. Either the operands' types must match, or the conversions
      from section 4.1.10 "Implicit Conversions" will be applied to obtain
      matching types. To do component-wise relational comparisons ...

    * The equality operators equal (==), and not equal (!=) operate on all
      types. They result in a scalar Boolean. If the operand types do not
      match, then there must be a conversion from section 4.1.10 "Implicit
      Conversions" applied to one operand that can make them match, in which
      case this conversion is done. For vectors, matrices, structures, ...

    * The ternary selection operator (?:). It operates on three expressions
      (exp1 ? exp2 : exp3). This operator evaluates the first expression,
      which must result in a scalar Boolean. If the result is true, it
      selects to evaluate the second expression, otherwise it selects to
      evaluate the third expression. Only one of the second and third
      expressions is evaluated. The second and third expressions can be any
      type, as long their types match, or there is a conversion in section
      4.1.10 "Implicit Conversions" that can be applied to one of the
      expressions to make their types match. This resulting matching type is
      the type of the entire expression.


    Modify Section 6.1, Function Definitions, p. 88

    (modify description of overloading)

    Function names can be overloaded.  The same function name can be used for
    multiple functions, as long as the parameter types differ.  If a function
    name is declared twice with the same parameter types, then the return
    types and all qualifiers must also match, and it is the same function
    being declared.  For example,

      vec4 f(in vec4 x, out vec4  y);   // (A)
      vec4 f(in vec4 x, out uvec4 y);   // (B) okay, different argument type
      vec4 f(in ivec4 x, out uvec4 y);  // (C) okay, different argument type

      int  f(in vec4 x, out ivec4 y);  // error, only return type differs
      vec4 f(in vec4 x, in  vec4  y);  // error, only qualifier differs
      vec4 f(const in vec4 x, out vec4 y);  // error, only qualifier differs

    When function calls are resolved, an exact type match for all the
    arguments is sought. If an exact match is found, all other functions are
    ignored, and the exact match is used. If no exact match is found, then
    the implicit conversions in section 4.1.10 (Implicit Conversions) will
    be applied to find a match. Mismatched types on input parameters ("in"
    or default) must have a conversion from the calling argument type to the
    formal parameter type. Mismatched types on output parameters ("out")
    must have a conversion from the formal parameter type to the calling
    argument type.

    If implicit conversions can be used to find more than one matching
    function, a single best-matching function is sought. To determine a best
    match, the conversions between calling argument and formal parameter
    types are compared for each function argument and pair of matching
    functions. After these comparisons are performed, each pair of matching
    functions are compared. A function definition A is considered a better
    match than function definition B if:

      * for at least one function argument, the conversion for that argument
        in A is better than the corresponding conversion in B; and

      * there is no function argument for which the conversion in B is
        better than the corresponding conversion in A.

    If a single function definition is considered a better match than every
    other matching function definition, it will be used. Otherwise, a
    compile-time semantic error for an ambiguous overloaded function call
    occurs.

    To determine whether the conversion for a single argument in one match
    is better than that for another match, the rule that an exact match is
    better than a match involving any implicit conversion is used.

    If this rule does not apply to a particular pair of conversions,
    neither conversion is considered better than the other.

    For the function prototypes (A), (B), and (C) above, the following
    examples show how the rules apply to different sets of calling argument
    types:

      f(vec4, vec4);        // exact match of vec4 f(in vec4 x, out vec4 y)
      f(vec4, uvec4);       // exact match of vec4 f(in vec4 x, out ivec4 y)
      f(ivec4, vec4);       // NOT matched.  All three match by implicit
                            //   conversion.  (C) is better than (A) and (B)
                            //   on the first argument.  (A) is better than
                            //   (B) and (C).

    User-defined functions can have multiple ...


New Implementation Dependent State

    None.

Issues

    Note: These issues apply specifically to the definition of the
    EXT_shader_implicit_conversions specification, which is based on the
    OpenGL extension ARB_gpu_shader5 as updated in OpenGL 4.x. Resolved issues
    from ARB_gpu_shader5 have been removed, but some remain applicable to this
    extension. ARB_gpu_shader5 can be found in the OpenGL Registry.

    (1) What functionality was removed relative to ARB_gpu_shader5?

      - everything unrelated to implicit conversions and function overloading.
      - Interactions with features not supported by the underlying
        ES 3.1 API and Shading Language, including:
        * interactions with ARB_gpu_shader_fp64 and NV_gpu_shader, including
          support for double-precision in implicit conversions and function
          overload resolution
        * shading language function overloading rules involving the type
          double

    (2) What functionality was changed and added relative to
        ARB_gpu_shader5?

        None.

    (3) Are the function overloading rules and examples correct?

    RESOLVED. Rules 2 and 3 as given in the GLSL 4.40 specification do not
    apply to ESSL, because there are no double types. There is a bug in the
    example

      f(vec4, ivec4);       // matched to vec4 f(in vec4 x, out vec4 y)
                            // (A) better than (B) for 2nd argument
                            //   argument (rule 2), same on first argument.

    both because this example is incorrect WRT the overloading rules
    starting with GLSL 4.00.4, and because the overloading rules in ESSL are
    simpler. This example has been removed (see bug 11178).

Revision History

    Revision 1, 2013/11/20 (Daniel Koch)
        - Initial version extracted from EXT_gpu_shader5 rev 2.

    Revision 2, 2013/11/21 (Jon Leech)
        - Resolve function overloading issue 7, per bug 11178.

    Revision 3, 2013/12/18 (Daniel Koch)
        - minor cleanup

    Revision 4, 2014/03/10 (Jon Leech)
        - Rebase on OpenGL ES 3.1 and change suffix to EXT.

    Revision 5, 2014/03/26 (Jon Leech)
        - Sync with released ES 3.1 specs.

    Revision 6, 2014/04/01 (Daniel Koch)
        - update contributors
