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

Elie Tournier tournier.elie at gmail.com
Fri Mar 3 16:23:00 UTC 2017


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

diff --git a/src/compiler/glsl/builtin_float64.h b/src/compiler/glsl/builtin_float64.h
index e614374d75..f8ceacdabf 100644
--- a/src/compiler/glsl/builtin_float64.h
+++ b/src/compiler/glsl/builtin_float64.h
@@ -155,3 +155,182 @@ feq64(void *mem_ctx, builtin_available_predicate avail)
    sig->replace_parameters(&sig_parameters);
    return sig;
 }
+ir_function_signature *
+extractFloat64Sign(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 r002D = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "a", ir_var_function_in);
+   sig_parameters.push_tail(r002D);
+   ir_expression *const r002E = rshift(swizzle_x(r002D), body.constant(int(31)));
+   body.emit(ret(r002E));
+
+   sig->replace_parameters(&sig_parameters);
+   return sig;
+}
+ir_function_signature *
+le64(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 r002F = new(mem_ctx) ir_variable(glsl_type::uint_type, "a0", ir_var_function_in);
+   sig_parameters.push_tail(r002F);
+   ir_variable *const r0030 = new(mem_ctx) ir_variable(glsl_type::uint_type, "a1", ir_var_function_in);
+   sig_parameters.push_tail(r0030);
+   ir_variable *const r0031 = new(mem_ctx) ir_variable(glsl_type::uint_type, "b0", ir_var_function_in);
+   sig_parameters.push_tail(r0031);
+   ir_variable *const r0032 = new(mem_ctx) ir_variable(glsl_type::uint_type, "b1", ir_var_function_in);
+   sig_parameters.push_tail(r0032);
+   ir_expression *const r0033 = less(r002F, r0031);
+   ir_expression *const r0034 = equal(r002F, r0031);
+   ir_expression *const r0035 = lequal(r0030, r0032);
+   ir_expression *const r0036 = logic_and(r0034, r0035);
+   ir_expression *const r0037 = logic_or(r0033, r0036);
+   body.emit(ret(r0037));
+
+   sig->replace_parameters(&sig_parameters);
+   return sig;
+}
+ir_function_signature *
+fle64(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 r0038 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "a", ir_var_function_in);
+   sig_parameters.push_tail(r0038);
+   ir_variable *const r0039 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "b", ir_var_function_in);
+   sig_parameters.push_tail(r0039);
+   ir_variable *const r003A = body.make_temp(glsl_type::bool_type, "return_value");
+   ir_variable *const r003B = new(mem_ctx) ir_variable(glsl_type::bool_type, "isbNaN", ir_var_auto);
+   body.emit(r003B);
+   ir_variable *const r003C = new(mem_ctx) ir_variable(glsl_type::bool_type, "isaNaN", ir_var_auto);
+   body.emit(r003C);
+   ir_variable *const r003D = body.make_temp(glsl_type::uvec2_type, "vec_ctor");
+   body.emit(assign(r003D, bit_and(swizzle_x(r0038), body.constant(1048575u)), 0x01));
+
+   body.emit(assign(r003D, swizzle_y(r0038), 0x02));
+
+   ir_variable *const r003E = body.make_temp(glsl_type::uvec2_type, "vec_ctor");
+   body.emit(assign(r003E, bit_and(swizzle_x(r0039), body.constant(1048575u)), 0x01));
+
+   body.emit(assign(r003E, swizzle_y(r0039), 0x02));
+
+   ir_expression *const r003F = rshift(swizzle_x(r0038), body.constant(int(20)));
+   ir_expression *const r0040 = bit_and(r003F, body.constant(2047u));
+   ir_expression *const r0041 = equal(r0040, body.constant(2047u));
+   ir_expression *const r0042 = bit_or(swizzle_x(r003D), swizzle_y(r0038));
+   ir_expression *const r0043 = nequal(r0042, body.constant(0u));
+   body.emit(assign(r003C, logic_and(r0041, r0043), 0x01));
+
+   ir_expression *const r0044 = rshift(swizzle_x(r0039), body.constant(int(20)));
+   ir_expression *const r0045 = bit_and(r0044, body.constant(2047u));
+   ir_expression *const r0046 = equal(r0045, body.constant(2047u));
+   ir_expression *const r0047 = bit_or(swizzle_x(r003E), swizzle_y(r0039));
+   ir_expression *const r0048 = nequal(r0047, body.constant(0u));
+   body.emit(assign(r003B, logic_and(r0046, r0048), 0x01));
+
+   /* IF CONDITION */
+   ir_expression *const r004A = logic_or(r003C, r003B);
+   ir_if *f0049 = new(mem_ctx) ir_if(operand(r004A).val);
+   exec_list *const f0049_parent_instructions = body.instructions;
+
+      /* THEN INSTRUCTIONS */
+      body.instructions = &f0049->then_instructions;
+
+      body.emit(assign(r003A, body.constant(false), 0x01));
+
+
+      /* ELSE INSTRUCTIONS */
+      body.instructions = &f0049->else_instructions;
+
+      ir_variable *const r004B = body.make_temp(glsl_type::uint_type, "extractFloat64Sign_retval");
+      body.emit(assign(r004B, rshift(swizzle_x(r0038), body.constant(int(31))), 0x01));
+
+      ir_variable *const r004C = body.make_temp(glsl_type::uint_type, "extractFloat64Sign_retval");
+      body.emit(assign(r004C, rshift(swizzle_x(r0039), body.constant(int(31))), 0x01));
+
+      /* IF CONDITION */
+      ir_expression *const r004E = nequal(r004B, r004C);
+      ir_if *f004D = new(mem_ctx) ir_if(operand(r004E).val);
+      exec_list *const f004D_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f004D->then_instructions;
+
+         ir_expression *const r004F = nequal(r004B, body.constant(0u));
+         ir_expression *const r0050 = bit_or(swizzle_x(r0038), swizzle_x(r0039));
+         ir_expression *const r0051 = lshift(r0050, body.constant(int(1)));
+         ir_expression *const r0052 = bit_or(r0051, swizzle_y(r0038));
+         ir_expression *const r0053 = bit_or(r0052, swizzle_y(r0039));
+         ir_expression *const r0054 = equal(r0053, body.constant(0u));
+         body.emit(assign(r003A, logic_or(r004F, r0054), 0x01));
+
+
+         /* ELSE INSTRUCTIONS */
+         body.instructions = &f004D->else_instructions;
+
+         ir_variable *const r0055 = body.make_temp(glsl_type::bool_type, "conditional_tmp");
+         /* IF CONDITION */
+         ir_expression *const r0057 = nequal(r004B, body.constant(0u));
+         ir_if *f0056 = new(mem_ctx) ir_if(operand(r0057).val);
+         exec_list *const f0056_parent_instructions = body.instructions;
+
+            /* THEN INSTRUCTIONS */
+            body.instructions = &f0056->then_instructions;
+
+            ir_expression *const r0058 = less(swizzle_x(r0039), swizzle_x(r0038));
+            ir_expression *const r0059 = equal(swizzle_x(r0039), swizzle_x(r0038));
+            ir_expression *const r005A = lequal(swizzle_y(r0039), swizzle_y(r0038));
+            ir_expression *const r005B = logic_and(r0059, r005A);
+            body.emit(assign(r0055, logic_or(r0058, r005B), 0x01));
+
+
+            /* ELSE INSTRUCTIONS */
+            body.instructions = &f0056->else_instructions;
+
+            ir_expression *const r005C = less(swizzle_x(r0038), swizzle_x(r0039));
+            ir_expression *const r005D = equal(swizzle_x(r0038), swizzle_x(r0039));
+            ir_expression *const r005E = lequal(swizzle_y(r0038), swizzle_y(r0039));
+            ir_expression *const r005F = logic_and(r005D, r005E);
+            body.emit(assign(r0055, logic_or(r005C, r005F), 0x01));
+
+
+         body.instructions = f0056_parent_instructions;
+         body.emit(f0056);
+
+         /* END IF */
+
+         body.emit(assign(r003A, r0055, 0x01));
+
+
+      body.instructions = f004D_parent_instructions;
+      body.emit(f004D);
+
+      /* END IF */
+
+
+   body.instructions = f0049_parent_instructions;
+   body.emit(f0049);
+
+   /* END IF */
+
+   body.emit(ret(r003A));
+
+   sig->replace_parameters(&sig_parameters);
+   return sig;
+}
diff --git a/src/compiler/glsl/builtin_functions.cpp b/src/compiler/glsl/builtin_functions.cpp
index 5e73d2469c..65ccf3725f 100644
--- a/src/compiler/glsl/builtin_functions.cpp
+++ b/src/compiler/glsl/builtin_functions.cpp
@@ -3141,6 +3141,10 @@ builtin_builder::create_builtins()
                 generate_ir::feq64(mem_ctx, integer_functions_supported),
                 NULL);
 
+   add_function("__builtin_fle64",
+                generate_ir::fle64(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 741698dc9e..e8b1ea0d79 100644
--- a/src/compiler/glsl/builtin_functions.h
+++ b/src/compiler/glsl/builtin_functions.h
@@ -72,6 +72,9 @@ fneg64(void *mem_ctx, builtin_available_predicate avail);
 ir_function_signature *
 feq64(void *mem_ctx, builtin_available_predicate avail);
 
+ir_function_signature *
+fle64(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 dc7668c18b..db86546f49 100644
--- a/src/compiler/glsl/float64.glsl
+++ b/src/compiler/glsl/float64.glsl
@@ -77,3 +77,55 @@ feq64( uvec2 a, uvec2 b )
         ( ( a.x == b.x ) ||
             ( ( a.y == 0u ) && ( ( ( a.x | b.x )<<1) == 0u ) ) );
 }
+
+/* Returns the sign bit of the double-precision floating-point value `a'.*/
+uint
+extractFloat64Sign( uvec2 a )
+{
+    return (a.x>>31);
+}
+
+/* Returns true if the 64-bit value formed by concatenating `a0' and `a1' is less
+ * than or equal to the 64-bit value formed by concatenating `b0' and `b1'.
+ * Otherwise, returns false.
+ */
+bool
+le64( uint a0, uint a1, uint b0, uint b1 )
+{
+    return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) );
+}
+
+/* Returns true if the double-precision floating-point value `a' is less than or
+ * equal to the corresponding value `b', and false otherwise.  The comparison is
+ * performed according to the IEEE Standard for Floating-Point Arithmetic.
+ */
+bool
+fle64( uvec2 a, uvec2 b )
+{
+    uint aSign;
+    uint bSign;
+    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;
+    }
+
+    aSign = extractFloat64Sign( a );
+    bSign = extractFloat64Sign( b );
+    if ( aSign != bSign ) {
+        return ( aSign != 0u ) ||
+            ( ( ( ( ( a.x | b.x )<<1 ) ) | a.y | b.y ) == 0u );
+    }
+    return ( aSign != 0u ) ? le64( b.x, b.y, a.x, a.y )
+        : le64( a.x, a.y, b.x, b.y );
+}
-- 
2.11.0



More information about the mesa-dev mailing list