[Mesa-dev] [RFC 02/11] glsl: Add "built-in" function to do neg(fp64)

Ian Romanick idr at freedesktop.org
Thu Mar 9 19:56:53 UTC 2017


On 03/03/2017 09:13 AM, Ilia Mirkin wrote:
> On Fri, Mar 3, 2017 at 11:57 AM, tournier.elie <tournier.elie at gmail.com> wrote:
>> On 3 March 2017 at 16:29, Ilia Mirkin <imirkin at alum.mit.edu> wrote:
>>> On Fri, Mar 3, 2017 at 11:22 AM, Elie Tournier <tournier.elie at gmail.com> wrote:
>>>> Signed-off-by: Elie Tournier <elie.tournier at collabora.com>
>>>> ---
>>>>  src/compiler/glsl/builtin_float64.h     | 19 +++++++++++++++++++
>>>>  src/compiler/glsl/builtin_functions.cpp |  4 ++++
>>>>  src/compiler/glsl/builtin_functions.h   |  3 +++
>>>>  src/compiler/glsl/float64.glsl          | 10 ++++++++++
>>>>  4 files changed, 36 insertions(+)
>>>>
>>>> diff --git a/src/compiler/glsl/builtin_float64.h b/src/compiler/glsl/builtin_float64.h
>>>> index c1ec89d210..6df91e10f5 100644
>>>> --- a/src/compiler/glsl/builtin_float64.h
>>>> +++ b/src/compiler/glsl/builtin_float64.h
>>>> @@ -17,3 +17,22 @@ fabs64(void *mem_ctx, builtin_available_predicate avail)
>>>>     sig->replace_parameters(&sig_parameters);
>>>>     return sig;
>>>>  }
>>>> +ir_function_signature *
>>>> +fneg64(void *mem_ctx, builtin_available_predicate avail)
>>>> +{
>>>> +   ir_function_signature *const sig =
>>>> +      new(mem_ctx) ir_function_signature(glsl_type::uvec2_type, avail);
>>>> +   ir_factory body(&sig->body, mem_ctx);
>>>> +   sig->is_defined = true;
>>>> +
>>>> +   exec_list sig_parameters;
>>>> +
>>>> +   ir_variable *const r000C = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "a", ir_var_function_in);
>>>> +   sig_parameters.push_tail(r000C);
>>>> +   body.emit(assign(r000C, bit_xor(swizzle_x(r000C), body.constant(2147483648u)), 0x01));
>>>> +
>>>> +   body.emit(ret(r000C));
>>>> +
>>>> +   sig->replace_parameters(&sig_parameters);
>>>> +   return sig;
>>>> +}
>>>> diff --git a/src/compiler/glsl/builtin_functions.cpp b/src/compiler/glsl/builtin_functions.cpp
>>>> index b0b1781725..a189b84190 100644
>>>> --- a/src/compiler/glsl/builtin_functions.cpp
>>>> +++ b/src/compiler/glsl/builtin_functions.cpp
>>>> @@ -3133,6 +3133,10 @@ builtin_builder::create_builtins()
>>>>                  generate_ir::fabs64(mem_ctx, integer_functions_supported),
>>>>                  NULL);
>>>>
>>>> +   add_function("__builtin_fneg64",
>>>> +                generate_ir::fneg64(mem_ctx, integer_functions_supported),
>>>> +                NULL);
>>>> +
>>>>  #undef F
>>>>  #undef FI
>>>>  #undef FIUD_VEC
>>>> diff --git a/src/compiler/glsl/builtin_functions.h b/src/compiler/glsl/builtin_functions.h
>>>> index abe02d97b6..37c6cc33c2 100644
>>>> --- a/src/compiler/glsl/builtin_functions.h
>>>> +++ b/src/compiler/glsl/builtin_functions.h
>>>> @@ -66,6 +66,9 @@ sign64(void *mem_ctx, builtin_available_predicate avail);
>>>>  ir_function_signature *
>>>>  fabs64(void *mem_ctx, builtin_available_predicate avail);
>>>>
>>>> +ir_function_signature *
>>>> +fneg64(void *mem_ctx, builtin_available_predicate avail);
>>>> +
>>>>  }
>>>>
>>>>  #endif /* BULITIN_FUNCTIONS_H */
>>>> diff --git a/src/compiler/glsl/float64.glsl b/src/compiler/glsl/float64.glsl
>>>> index b8f0c2e444..82875e9407 100644
>>>> --- a/src/compiler/glsl/float64.glsl
>>>> +++ b/src/compiler/glsl/float64.glsl
>>>> @@ -26,3 +26,13 @@ fabs64( uvec2 a )
>>>>      a.x &= 0x7FFFFFFFu;
>>>>      return a;
>>>>  }
>>>> +
>>>> +/* Negate value of a Float64 :
>>>> + * Toggle the sign bit
>>>> + */
>>>> +uvec2
>>>> +fneg64( uvec2 a )
>>>> +{
>>>> +    a.x ^= (1u<<31);
>>>
>>> Is this right for NaN? Presumably neg(NaN) should == NaN.
>>
>> The IEEE 754 standard say :
>>
>> " 6.3 The sign bit
>>
>> When either an input or result is NaN, this standard does not
>> interpret the sign of a NaN. Note, however,
>> that operations on bit strings copy, negate, abs, copySign specify the
>> sign bit of a NaN result,
>> sometimes based upon the sign bit of a NaN operand. The logical
>> predicate totalOrder is also affected by
>> the sign bit of a NaN operand. For all other operations, this standard
>> does not specify the sign bit of a NaN
>> result, even when there is only one input NaN, or when the NaN is
>> produced from an invalid operation. "
>>
>> So neg(NaN) == NaN
> 
> Right ... I guess I meant that there's a certain amount of
> normalization that's required to be applied to results of floating
> point operations. I was wondering if the sign bit of a NaN had to be
> cleared, so that it would be in canonical form. (Just like you'd set
> all of the mantissa bits, even though setting any of them results in a
> NaN when exp == 0x7ff.) You've been digging in the FP64 standard a lot
> more than I have, so if you think it's acceptable to have a fp64
> function return a NaN with the sign bit set, that's fine by me.

This would be easy enough to test, and we probably should.  We can check
unpackDouble2x32(-packDouble2x32(uvec2_that_is_NAN)) ==
unpackDouble2x32(packDouble2x32(uvec2_that_is_NAN)).  We could also
check this on a CPU.

>   -ilia



More information about the mesa-dev mailing list