[Mesa-dev] [RFC 03/11] glsl: Add "built-in" functions to do eq(fp64, fp64)

Elie Tournier tournier.elie at gmail.com
Fri Mar 3 16:22:59 UTC 2017


Signed-off-by: Elie Tournier <elie.tournier at collabora.com>
---
 src/compiler/glsl/builtin_float64.h     | 119 ++++++++++++++++++++++++++++++++
 src/compiler/glsl/builtin_functions.cpp |   4 ++
 src/compiler/glsl/builtin_functions.h   |   3 +
 src/compiler/glsl/float64.glsl          |  41 +++++++++++
 4 files changed, 167 insertions(+)

diff --git a/src/compiler/glsl/builtin_float64.h b/src/compiler/glsl/builtin_float64.h
index 6df91e10f5..e614374d75 100644
--- a/src/compiler/glsl/builtin_float64.h
+++ b/src/compiler/glsl/builtin_float64.h
@@ -36,3 +36,122 @@ fneg64(void *mem_ctx, builtin_available_predicate avail)
    sig->replace_parameters(&sig_parameters);
    return sig;
 }
+ir_function_signature *
+extractFloat64Frac(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 r000D = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "a", ir_var_function_in);
+   sig_parameters.push_tail(r000D);
+   ir_variable *const r000E = body.make_temp(glsl_type::uvec2_type, "vec_ctor");
+   body.emit(assign(r000E, bit_and(swizzle_x(r000D), body.constant(1048575u)), 0x01));
+
+   body.emit(assign(r000E, swizzle_y(r000D), 0x02));
+
+   body.emit(ret(r000E));
+
+   sig->replace_parameters(&sig_parameters);
+   return sig;
+}
+ir_function_signature *
+extractFloat64Exp(void *mem_ctx, builtin_available_predicate avail)
+{
+   ir_function_signature *const sig =
+      new(mem_ctx) ir_function_signature(glsl_type::uint_type, avail);
+   ir_factory body(&sig->body, mem_ctx);
+   sig->is_defined = true;
+
+   exec_list sig_parameters;
+
+   ir_variable *const r000F = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "a", ir_var_function_in);
+   sig_parameters.push_tail(r000F);
+   ir_expression *const r0010 = rshift(swizzle_x(r000F), body.constant(int(20)));
+   ir_expression *const r0011 = bit_and(r0010, body.constant(2047u));
+   body.emit(ret(r0011));
+
+   sig->replace_parameters(&sig_parameters);
+   return sig;
+}
+ir_function_signature *
+feq64(void *mem_ctx, builtin_available_predicate avail)
+{
+   ir_function_signature *const sig =
+      new(mem_ctx) ir_function_signature(glsl_type::bool_type, avail);
+   ir_factory body(&sig->body, mem_ctx);
+   sig->is_defined = true;
+
+   exec_list sig_parameters;
+
+   ir_variable *const r0012 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "a", ir_var_function_in);
+   sig_parameters.push_tail(r0012);
+   ir_variable *const r0013 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "b", ir_var_function_in);
+   sig_parameters.push_tail(r0013);
+   ir_variable *const r0014 = body.make_temp(glsl_type::bool_type, "return_value");
+   ir_variable *const r0015 = new(mem_ctx) ir_variable(glsl_type::bool_type, "isbNaN", ir_var_auto);
+   body.emit(r0015);
+   ir_variable *const r0016 = new(mem_ctx) ir_variable(glsl_type::bool_type, "isaNaN", ir_var_auto);
+   body.emit(r0016);
+   ir_variable *const r0017 = body.make_temp(glsl_type::uvec2_type, "vec_ctor");
+   body.emit(assign(r0017, bit_and(swizzle_x(r0012), body.constant(1048575u)), 0x01));
+
+   body.emit(assign(r0017, swizzle_y(r0012), 0x02));
+
+   ir_variable *const r0018 = body.make_temp(glsl_type::uvec2_type, "vec_ctor");
+   body.emit(assign(r0018, bit_and(swizzle_x(r0013), body.constant(1048575u)), 0x01));
+
+   body.emit(assign(r0018, swizzle_y(r0013), 0x02));
+
+   ir_expression *const r0019 = rshift(swizzle_x(r0012), body.constant(int(20)));
+   ir_expression *const r001A = bit_and(r0019, body.constant(2047u));
+   ir_expression *const r001B = equal(r001A, body.constant(2047u));
+   ir_expression *const r001C = bit_or(swizzle_x(r0017), swizzle_y(r0012));
+   ir_expression *const r001D = nequal(r001C, body.constant(0u));
+   body.emit(assign(r0016, logic_and(r001B, r001D), 0x01));
+
+   ir_expression *const r001E = rshift(swizzle_x(r0013), body.constant(int(20)));
+   ir_expression *const r001F = bit_and(r001E, body.constant(2047u));
+   ir_expression *const r0020 = equal(r001F, body.constant(2047u));
+   ir_expression *const r0021 = bit_or(swizzle_x(r0018), swizzle_y(r0013));
+   ir_expression *const r0022 = nequal(r0021, body.constant(0u));
+   body.emit(assign(r0015, logic_and(r0020, r0022), 0x01));
+
+   /* IF CONDITION */
+   ir_expression *const r0024 = logic_or(r0016, r0015);
+   ir_if *f0023 = new(mem_ctx) ir_if(operand(r0024).val);
+   exec_list *const f0023_parent_instructions = body.instructions;
+
+      /* THEN INSTRUCTIONS */
+      body.instructions = &f0023->then_instructions;
+
+      body.emit(assign(r0014, body.constant(false), 0x01));
+
+
+      /* ELSE INSTRUCTIONS */
+      body.instructions = &f0023->else_instructions;
+
+      ir_expression *const r0025 = equal(swizzle_y(r0012), swizzle_y(r0013));
+      ir_expression *const r0026 = equal(swizzle_x(r0012), swizzle_x(r0013));
+      ir_expression *const r0027 = equal(swizzle_y(r0012), body.constant(0u));
+      ir_expression *const r0028 = bit_or(swizzle_x(r0012), swizzle_x(r0013));
+      ir_expression *const r0029 = lshift(r0028, body.constant(int(1)));
+      ir_expression *const r002A = equal(r0029, body.constant(0u));
+      ir_expression *const r002B = logic_and(r0027, r002A);
+      ir_expression *const r002C = logic_or(r0026, r002B);
+      body.emit(assign(r0014, logic_and(r0025, r002C), 0x01));
+
+
+   body.instructions = f0023_parent_instructions;
+   body.emit(f0023);
+
+   /* END IF */
+
+   body.emit(ret(r0014));
+
+   sig->replace_parameters(&sig_parameters);
+   return sig;
+}
diff --git a/src/compiler/glsl/builtin_functions.cpp b/src/compiler/glsl/builtin_functions.cpp
index a189b84190..5e73d2469c 100644
--- a/src/compiler/glsl/builtin_functions.cpp
+++ b/src/compiler/glsl/builtin_functions.cpp
@@ -3137,6 +3137,10 @@ builtin_builder::create_builtins()
                 generate_ir::fneg64(mem_ctx, integer_functions_supported),
                 NULL);
 
+   add_function("__builtin_feq64",
+                generate_ir::feq64(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 37c6cc33c2..741698dc9e 100644
--- a/src/compiler/glsl/builtin_functions.h
+++ b/src/compiler/glsl/builtin_functions.h
@@ -69,6 +69,9 @@ fabs64(void *mem_ctx, builtin_available_predicate avail);
 ir_function_signature *
 fneg64(void *mem_ctx, builtin_available_predicate avail);
 
+ir_function_signature *
+feq64(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 82875e9407..dc7668c18b 100644
--- a/src/compiler/glsl/float64.glsl
+++ b/src/compiler/glsl/float64.glsl
@@ -36,3 +36,44 @@ fneg64( uvec2 a )
     a.x ^= (1u<<31);
     return a;
 }
+
+/* Returns the fraction bits of the double-precision floating-point value `a'.*/
+uvec2
+extractFloat64Frac( uvec2 a )
+{
+    return uvec2( a.x & 0x000FFFFFu, a.y );
+}
+
+/* Returns the exponent bits of the double-precision floating-point value `a'.*/
+uint
+extractFloat64Exp( uvec2 a )
+{
+    return (a.x>>20) & 0x7FFu;
+}
+
+/* Returns true if the double-precision floating-point value `a' is equal to the
+ * corresponding value `b', and false otherwise.  The comparison is performed
+ * according to the IEEE Standard for Floating-Point Arithmetic.
+ */
+bool
+feq64( uvec2 a, uvec2 b )
+{
+    uvec2 aFrac;
+    uvec2 bFrac;
+    bool isaNaN;
+    bool isbNaN;
+
+    aFrac = extractFloat64Frac( a );
+    bFrac = extractFloat64Frac( b );
+    isaNaN = ( extractFloat64Exp( a ) == 0x7FFu ) &&
+        ( ( aFrac.x | aFrac.y ) != 0u );
+    isbNaN = ( extractFloat64Exp( b ) == 0x7FFu ) &&
+       ( ( bFrac.x | bFrac.y ) != 0u );
+
+    if ( isaNaN || isbNaN ) {
+        return false;
+    }
+    return ( a.y == b.y ) &&
+        ( ( a.x == b.x ) ||
+            ( ( a.y == 0u ) && ( ( ( a.x | b.x )<<1) == 0u ) ) );
+}
-- 
2.11.0



More information about the mesa-dev mailing list