EXT_shader_implicit_conversions

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 and 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