[Mesa-dev] [PATCH 11/47] glsl: Add "built-in" functions to do fp64_to_int(fp64)

Elie Tournier tournier.elie at gmail.com
Wed Aug 23 11:07:41 UTC 2017


Signed-off-by: Elie Tournier <elie.tournier at collabora.com>
---
 src/compiler/glsl/builtin_float64.h     | 284 ++++++++++++++++++++++++++++++++
 src/compiler/glsl/builtin_functions.cpp |   4 +
 src/compiler/glsl/builtin_functions.h   |   3 +
 src/compiler/glsl/float64.glsl          |  45 +++++
 src/compiler/glsl/glcpp/glcpp-parse.y   |   1 +
 5 files changed, 337 insertions(+)

diff --git a/src/compiler/glsl/builtin_float64.h b/src/compiler/glsl/builtin_float64.h
index 2c11e463ca..c5640c459a 100644
--- a/src/compiler/glsl/builtin_float64.h
+++ b/src/compiler/glsl/builtin_float64.h
@@ -12553,3 +12553,287 @@ uint_to_fp64(void *mem_ctx, builtin_available_predicate avail)
    sig->replace_parameters(&sig_parameters);
    return sig;
 }
+ir_function_signature *
+fp64_to_int(void *mem_ctx, builtin_available_predicate avail)
+{
+   ir_function_signature *const sig =
+      new(mem_ctx) ir_function_signature(glsl_type::int_type, avail);
+   ir_factory body(&sig->body, mem_ctx);
+   sig->is_defined = true;
+
+   exec_list sig_parameters;
+
+   ir_variable *const r0A87 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "a", ir_var_function_in);
+   sig_parameters.push_tail(r0A87);
+   ir_variable *const r0A88 = body.make_temp(glsl_type::bool_type, "execute_flag");
+   body.emit(assign(r0A88, body.constant(true), 0x01));
+
+   ir_variable *const r0A89 = body.make_temp(glsl_type::int_type, "return_value");
+   ir_variable *const r0A8A = new(mem_ctx) ir_variable(glsl_type::uint_type, "absZ", ir_var_auto);
+   body.emit(r0A8A);
+   ir_variable *const r0A8B = new(mem_ctx) ir_variable(glsl_type::uint_type, "aSign", ir_var_auto);
+   body.emit(r0A8B);
+   ir_variable *const r0A8C = new(mem_ctx) ir_variable(glsl_type::uint_type, "aFracHi", ir_var_auto);
+   body.emit(r0A8C);
+   ir_variable *const r0A8D = body.make_temp(glsl_type::uint_type, "extractFloat64FracHi_retval");
+   body.emit(assign(r0A8D, bit_and(swizzle_y(r0A87), body.constant(1048575u)), 0x01));
+
+   body.emit(assign(r0A8C, r0A8D, 0x01));
+
+   ir_variable *const r0A8E = body.make_temp(glsl_type::int_type, "extractFloat64Exp_retval");
+   ir_expression *const r0A8F = rshift(swizzle_y(r0A87), body.constant(int(20)));
+   ir_expression *const r0A90 = bit_and(r0A8F, body.constant(2047u));
+   body.emit(assign(r0A8E, expr(ir_unop_u2i, r0A90), 0x01));
+
+   body.emit(assign(r0A8B, rshift(swizzle_y(r0A87), body.constant(int(31))), 0x01));
+
+   body.emit(assign(r0A8A, body.constant(0u), 0x01));
+
+   ir_variable *const r0A91 = body.make_temp(glsl_type::int_type, "assignment_tmp");
+   body.emit(assign(r0A91, add(r0A8E, body.constant(int(-1043))), 0x01));
+
+   /* IF CONDITION */
+   ir_expression *const r0A93 = lequal(body.constant(int(0)), r0A91);
+   ir_if *f0A92 = new(mem_ctx) ir_if(operand(r0A93).val);
+   exec_list *const f0A92_parent_instructions = body.instructions;
+
+      /* THEN INSTRUCTIONS */
+      body.instructions = &f0A92->then_instructions;
+
+      /* IF CONDITION */
+      ir_expression *const r0A95 = less(body.constant(int(1054)), r0A8E);
+      ir_if *f0A94 = new(mem_ctx) ir_if(operand(r0A95).val);
+      exec_list *const f0A94_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f0A94->then_instructions;
+
+         /* IF CONDITION */
+         ir_expression *const r0A97 = equal(r0A8E, body.constant(int(2047)));
+         ir_expression *const r0A98 = bit_or(r0A8D, swizzle_x(r0A87));
+         ir_expression *const r0A99 = expr(ir_unop_u2i, r0A98);
+         ir_expression *const r0A9A = expr(ir_unop_i2b, r0A99);
+         ir_expression *const r0A9B = logic_and(r0A97, r0A9A);
+         ir_if *f0A96 = new(mem_ctx) ir_if(operand(r0A9B).val);
+         exec_list *const f0A96_parent_instructions = body.instructions;
+
+            /* THEN INSTRUCTIONS */
+            body.instructions = &f0A96->then_instructions;
+
+            body.emit(assign(r0A8B, body.constant(0u), 0x01));
+
+
+         body.instructions = f0A96_parent_instructions;
+         body.emit(f0A96);
+
+         /* END IF */
+
+         ir_variable *const r0A9C = body.make_temp(glsl_type::int_type, "conditional_tmp");
+         /* IF CONDITION */
+         ir_expression *const r0A9E = expr(ir_unop_u2i, r0A8B);
+         ir_expression *const r0A9F = expr(ir_unop_i2b, r0A9E);
+         ir_if *f0A9D = new(mem_ctx) ir_if(operand(r0A9F).val);
+         exec_list *const f0A9D_parent_instructions = body.instructions;
+
+            /* THEN INSTRUCTIONS */
+            body.instructions = &f0A9D->then_instructions;
+
+            body.emit(assign(r0A9C, body.constant(int(-2147483648)), 0x01));
+
+
+            /* ELSE INSTRUCTIONS */
+            body.instructions = &f0A9D->else_instructions;
+
+            body.emit(assign(r0A9C, body.constant(int(2147483647)), 0x01));
+
+
+         body.instructions = f0A9D_parent_instructions;
+         body.emit(f0A9D);
+
+         /* END IF */
+
+         body.emit(assign(r0A89, r0A9C, 0x01));
+
+         body.emit(assign(r0A88, body.constant(false), 0x01));
+
+
+         /* ELSE INSTRUCTIONS */
+         body.instructions = &f0A94->else_instructions;
+
+         ir_variable *const r0AA0 = body.make_temp(glsl_type::uint_type, "a0");
+         body.emit(assign(r0AA0, bit_or(r0A8D, body.constant(1048576u)), 0x01));
+
+         ir_variable *const r0AA1 = body.make_temp(glsl_type::uint_type, "z1Ptr");
+         body.emit(assign(r0AA1, lshift(swizzle_x(r0A87), r0A91), 0x01));
+
+         ir_variable *const r0AA2 = body.make_temp(glsl_type::uint_type, "conditional_tmp");
+         /* IF CONDITION */
+         ir_expression *const r0AA4 = equal(r0A91, body.constant(int(0)));
+         ir_if *f0AA3 = new(mem_ctx) ir_if(operand(r0AA4).val);
+         exec_list *const f0AA3_parent_instructions = body.instructions;
+
+            /* THEN INSTRUCTIONS */
+            body.instructions = &f0AA3->then_instructions;
+
+            body.emit(assign(r0AA2, r0AA0, 0x01));
+
+
+            /* ELSE INSTRUCTIONS */
+            body.instructions = &f0AA3->else_instructions;
+
+            ir_expression *const r0AA5 = lshift(r0AA0, r0A91);
+            ir_expression *const r0AA6 = neg(r0A91);
+            ir_expression *const r0AA7 = bit_and(r0AA6, body.constant(int(31)));
+            ir_expression *const r0AA8 = rshift(swizzle_x(r0A87), r0AA7);
+            body.emit(assign(r0AA2, bit_or(r0AA5, r0AA8), 0x01));
+
+
+         body.instructions = f0AA3_parent_instructions;
+         body.emit(f0AA3);
+
+         /* END IF */
+
+         body.emit(assign(r0A8A, r0AA2, 0x01));
+
+
+      body.instructions = f0A94_parent_instructions;
+      body.emit(f0A94);
+
+      /* END IF */
+
+
+      /* ELSE INSTRUCTIONS */
+      body.instructions = &f0A92->else_instructions;
+
+      /* IF CONDITION */
+      ir_expression *const r0AAA = less(r0A8E, body.constant(int(1023)));
+      ir_if *f0AA9 = new(mem_ctx) ir_if(operand(r0AAA).val);
+      exec_list *const f0AA9_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f0AA9->then_instructions;
+
+         body.emit(assign(r0A89, body.constant(int(0)), 0x01));
+
+         body.emit(assign(r0A88, body.constant(false), 0x01));
+
+
+         /* ELSE INSTRUCTIONS */
+         body.instructions = &f0AA9->else_instructions;
+
+         body.emit(assign(r0A8C, bit_or(r0A8D, body.constant(1048576u)), 0x01));
+
+         ir_expression *const r0AAB = neg(r0A91);
+         body.emit(assign(r0A8A, rshift(r0A8C, r0AAB), 0x01));
+
+
+      body.instructions = f0AA9_parent_instructions;
+      body.emit(f0AA9);
+
+      /* END IF */
+
+
+   body.instructions = f0A92_parent_instructions;
+   body.emit(f0A92);
+
+   /* END IF */
+
+   /* IF CONDITION */
+   ir_if *f0AAC = new(mem_ctx) ir_if(operand(r0A88).val);
+   exec_list *const f0AAC_parent_instructions = body.instructions;
+
+      /* THEN INSTRUCTIONS */
+      body.instructions = &f0AAC->then_instructions;
+
+      ir_variable *const r0AAD = body.make_temp(glsl_type::int_type, "conditional_tmp");
+      /* IF CONDITION */
+      ir_expression *const r0AAF = nequal(r0A8B, body.constant(0u));
+      ir_if *f0AAE = new(mem_ctx) ir_if(operand(r0AAF).val);
+      exec_list *const f0AAE_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f0AAE->then_instructions;
+
+         ir_expression *const r0AB0 = expr(ir_unop_u2i, r0A8A);
+         body.emit(assign(r0AAD, neg(r0AB0), 0x01));
+
+
+         /* ELSE INSTRUCTIONS */
+         body.instructions = &f0AAE->else_instructions;
+
+         body.emit(assign(r0AAD, expr(ir_unop_u2i, r0A8A), 0x01));
+
+
+      body.instructions = f0AAE_parent_instructions;
+      body.emit(f0AAE);
+
+      /* END IF */
+
+      /* IF CONDITION */
+      ir_expression *const r0AB2 = less(r0AAD, body.constant(int(0)));
+      ir_expression *const r0AB3 = expr(ir_unop_b2i, r0AB2);
+      ir_expression *const r0AB4 = expr(ir_unop_i2u, r0AB3);
+      ir_expression *const r0AB5 = bit_xor(r0A8B, r0AB4);
+      ir_expression *const r0AB6 = expr(ir_unop_u2i, r0AB5);
+      ir_expression *const r0AB7 = expr(ir_unop_i2b, r0AB6);
+      ir_expression *const r0AB8 = expr(ir_unop_i2b, r0AAD);
+      ir_expression *const r0AB9 = logic_and(r0AB7, r0AB8);
+      ir_if *f0AB1 = new(mem_ctx) ir_if(operand(r0AB9).val);
+      exec_list *const f0AB1_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f0AB1->then_instructions;
+
+         ir_variable *const r0ABA = body.make_temp(glsl_type::int_type, "conditional_tmp");
+         /* IF CONDITION */
+         ir_expression *const r0ABC = expr(ir_unop_u2i, r0A8B);
+         ir_expression *const r0ABD = expr(ir_unop_i2b, r0ABC);
+         ir_if *f0ABB = new(mem_ctx) ir_if(operand(r0ABD).val);
+         exec_list *const f0ABB_parent_instructions = body.instructions;
+
+            /* THEN INSTRUCTIONS */
+            body.instructions = &f0ABB->then_instructions;
+
+            body.emit(assign(r0ABA, body.constant(int(-2147483648)), 0x01));
+
+
+            /* ELSE INSTRUCTIONS */
+            body.instructions = &f0ABB->else_instructions;
+
+            body.emit(assign(r0ABA, body.constant(int(2147483647)), 0x01));
+
+
+         body.instructions = f0ABB_parent_instructions;
+         body.emit(f0ABB);
+
+         /* END IF */
+
+         body.emit(assign(r0A89, r0ABA, 0x01));
+
+         body.emit(assign(r0A88, body.constant(false), 0x01));
+
+
+         /* ELSE INSTRUCTIONS */
+         body.instructions = &f0AB1->else_instructions;
+
+         body.emit(assign(r0A89, r0AAD, 0x01));
+
+         body.emit(assign(r0A88, body.constant(false), 0x01));
+
+
+      body.instructions = f0AB1_parent_instructions;
+      body.emit(f0AB1);
+
+      /* END IF */
+
+
+   body.instructions = f0AAC_parent_instructions;
+   body.emit(f0AAC);
+
+   /* END IF */
+
+   body.emit(ret(r0A89));
+
+   sig->replace_parameters(&sig_parameters);
+   return sig;
+}
diff --git a/src/compiler/glsl/builtin_functions.cpp b/src/compiler/glsl/builtin_functions.cpp
index c2adc884d3..53491d8c38 100644
--- a/src/compiler/glsl/builtin_functions.cpp
+++ b/src/compiler/glsl/builtin_functions.cpp
@@ -3364,6 +3364,10 @@ builtin_builder::create_builtins()
                 generate_ir::uint_to_fp64(mem_ctx, integer_functions_supported),
                 NULL);
 
+   add_function("__builtin_fp64_to_int",
+                generate_ir::fp64_to_int(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 f30e7a7967..3adb2d230f 100644
--- a/src/compiler/glsl/builtin_functions.h
+++ b/src/compiler/glsl/builtin_functions.h
@@ -97,6 +97,9 @@ fp64_to_uint(void *mem_ctx, builtin_available_predicate avail);
 ir_function_signature *
 uint_to_fp64(void *mem_ctx, builtin_available_predicate avail);
 
+ir_function_signature *
+fp64_to_int(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 fb81e171e9..a9cffd4f9b 100644
--- a/src/compiler/glsl/float64.glsl
+++ b/src/compiler/glsl/float64.glsl
@@ -931,3 +931,48 @@ uint_to_fp64(uint a)
 
    return packFloat64(0u, 0x432 - shiftDist, aHigh, aLow);
 }
+
+/* Returns the result of converting the double-precision floating-point value
+ * `a' to the 32-bit two's complement integer format.  The conversion is
+ * performed according to the IEEE Standard for Floating-Point Arithmetic---
+ * which means in particular that the conversion is rounded according to the
+ * current rounding mode.  If `a' is a NaN, the largest positive integer is
+ * returned.  Otherwise, if the conversion overflows, the largest integer with
+ * the same sign as `a' is returned.
+ */
+int
+fp64_to_int(uvec2 a)
+{
+   uint aFracLo = extractFloat64FracLo(a);
+   uint aFracHi = extractFloat64FracHi(a);
+   int aExp = extractFloat64Exp(a);
+   uint aSign = extractFloat64Sign(a);
+
+   uint absZ = 0u;
+   uint aFracExtra = 0u;
+   int z;
+   int shiftCount = aExp - 0x413;
+
+   if (0 <= shiftCount) {
+      if (0x41E < aExp) {
+         if ((aExp == 0x7FF) && bool(aFracHi | aFracLo))
+            aSign = 0u;
+         return bool(aSign) ? 0x80000000 : 0x7FFFFFFF;
+      }
+      shortShift64Left(aFracHi | 0x00100000u, aFracLo, shiftCount, absZ, aFracExtra);
+   } else {
+      if (aExp < 0x3FF)
+         return 0;
+
+      aFracHi |= 0x00100000u;
+      aFracExtra = ( aFracHi << (shiftCount & 31)) | aFracLo;
+      absZ = aFracHi >> (- shiftCount);
+   }
+
+   z = (aSign != 0u) ? - int(absZ) : int(absZ);
+
+   if (bool(aSign ^ uint(z < 0)) && bool(z))
+      return bool(aSign) ? 0x80000000 : 0x7FFFFFFF;
+
+   return z;
+}
diff --git a/src/compiler/glsl/glcpp/glcpp-parse.y b/src/compiler/glsl/glcpp/glcpp-parse.y
index f833dc0dd0..ff501b69e1 100644
--- a/src/compiler/glsl/glcpp/glcpp-parse.y
+++ b/src/compiler/glsl/glcpp/glcpp-parse.y
@@ -2459,6 +2459,7 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio
          add_builtin_define(parser, "__have_builtin_builtin_fmul64", 1);
          add_builtin_define(parser, "__have_builtin_builtin_fp64_to_uint", 1);
          add_builtin_define(parser, "__have_builtin_builtin_uint_to_fp64", 1);
+         add_builtin_define(parser, "__have_builtin_builtin_fp64_to_int", 1);
       }
    }
 
-- 
2.14.1



More information about the mesa-dev mailing list