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 : where 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