[Mesa-dev] [PATCH 5/5] glsl: Add frexp signatures and implementation.
Matt Turner
mattst88 at gmail.com
Wed Sep 11 21:54:46 PDT 2013
On Wed, Sep 11, 2013 at 10:03 AM, Paul Berry <stereotype441 at gmail.com> wrote:
> On 9 September 2013 15:14, Matt Turner <mattst88 at gmail.com> wrote:
>>
>> I initially implemented frexp() as an IR opcode with a lowering pass,
>> but since it returns a value and has an out-parameter, it would break
>> assumptions our optimization passes make about ir_expressions being pure
>> (i.e., having no side effects).
>>
>> For example, if opt_tree_grafting encounters this code:
>>
>> uniform float u;
>> void main()
>> {
>> int exp;
>> float f = frexp(u, out exp);
>> float g = float(exp)/256.0;
>> float h = float(exp) + 1.0;
>> gl_FragColor = vec4(f, g, h, g + h);
>> }
>>
>> it may try to optimize it to this:
>>
>> uniform float u;
>> void main()
>> {
>> int exp;
>> float g = float(exp)/256.0;
>> float h = float(exp) + 1.0;
>> gl_FragColor = vec4(frexp(u, out exp), g, h, g + h);
>> }
>>
>> Some hardware has an instruction which performs frexp(), but we would
>> need some other compiler infrastructure to be able to generate it, such
>> as an intrinsics system that would allow backends to emit specific code
>> for particular bits of IR.
>> ---
>> src/glsl/builtin_functions.cpp | 54
>> ++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 54 insertions(+)
>>
>> diff --git a/src/glsl/builtin_functions.cpp
>> b/src/glsl/builtin_functions.cpp
>> index dbd35f2..e9d7b74 100644
>> --- a/src/glsl/builtin_functions.cpp
>> +++ b/src/glsl/builtin_functions.cpp
>> @@ -512,6 +512,7 @@ private:
>> B1(findMSB)
>> B1(fma)
>> B2(ldexp)
>> + B2(frexp)
>> #undef B0
>> #undef B1
>> #undef B2
>> @@ -1828,6 +1829,13 @@ builtin_builder::create_builtins()
>> _ldexp(glsl_type::vec3_type, glsl_type::ivec3_type),
>> _ldexp(glsl_type::vec4_type, glsl_type::ivec4_type),
>> NULL);
>> +
>> + add_function("frexp",
>> + _frexp(glsl_type::float_type, glsl_type::int_type),
>> + _frexp(glsl_type::vec2_type, glsl_type::ivec2_type),
>> + _frexp(glsl_type::vec3_type, glsl_type::ivec3_type),
>> + _frexp(glsl_type::vec4_type, glsl_type::ivec4_type),
>> + NULL);
>> #undef F
>> #undef FI
>> #undef FIU
>> @@ -3524,6 +3532,52 @@ builtin_builder::_ldexp(const glsl_type *x_type,
>> const glsl_type *exp_type)
>> {
>> return binop(ir_binop_ldexp, gpu_shader5, x_type, x_type, exp_type);
>> }
>> +
>> +ir_function_signature *
>> +builtin_builder::_frexp(const glsl_type *x_type, const glsl_type
>> *exp_type)
>> +{
>> + ir_variable *x = in_var(x_type, "x");
>> + ir_variable *exponent = out_var(exp_type, "exp");
>> + MAKE_SIG(x_type, gpu_shader5, 2, x, exponent);
>> +
>> + const unsigned vec_elem = x_type->vector_elements;
>> + const glsl_type *bvec = glsl_type::get_instance(GLSL_TYPE_BOOL,
>> vec_elem, 1);
>> + const glsl_type *uvec = glsl_type::get_instance(GLSL_TYPE_UINT,
>> vec_elem, 1);
>> +
>> + /* Single-precision floating-point values are stored as
>> + * 1 sign bit;
>> + * 8 exponent bits;
>> + * 23 mantissa bits.
>> + *
>> + * An exponent shift of 23 will shift the mantissa out, leaving only
>> the
>> + * exponent and sign bit (which itself may be zero, if the absolute
>> value
>> + * was taken before the bitcast and shift.
>> + */
>> + ir_constant *exponent_shift = imm(23);
>> + ir_constant *exponent_bias = imm(-126, vec_elem);
>> +
>> + ir_constant *sign_mantissa_mask = imm(0x807fffffu, vec_elem);
>> + ir_constant *exponent_mask = imm(0x3f000000u, vec_elem);
>
>
> Actually the exponent mask would be 0x7f800000u. This is the exponent
> *value* corresponding to a float in the range [0.5, 1.0). Fortunately
> that's what we use it for :). I'd propose renaming it to something like
> "exponent_value", and maybe adding an explanatory comment.
Indeed you are correct. Thanks for catching this, I'll rename it and
add a comment.
Thanks for the review, and sorry I'm not around this week to do the same.
Matt
More information about the mesa-dev
mailing list