[Mesa-dev] [PATCH 11/50] glsl: Add "built-in" functions to do fp64_to_int(fp64) (v2)
Dave Airlie
airlied at gmail.com
Tue Mar 13 04:24:36 UTC 2018
From: Elie Tournier <tournier.elie at gmail.com>
v2: use mix
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 | 41 ++++++++
src/compiler/glsl/glcpp/glcpp-parse.y | 1 +
5 files changed, 228 insertions(+)
diff --git a/src/compiler/glsl/builtin_float64.h b/src/compiler/glsl/builtin_float64.h
index c200447..8ce2baa 100644
--- a/src/compiler/glsl/builtin_float64.h
+++ b/src/compiler/glsl/builtin_float64.h
@@ -5354,3 +5354,182 @@ 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 r088E = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "a", ir_var_function_in);
+ sig_parameters.push_tail(r088E);
+ ir_variable *const r088F = body.make_temp(glsl_type::bool_type, "execute_flag");
+ body.emit(assign(r088F, body.constant(true), 0x01));
+
+ ir_variable *const r0890 = body.make_temp(glsl_type::int_type, "return_value");
+ ir_variable *const r0891 = new(mem_ctx) ir_variable(glsl_type::uint_type, "absZ", ir_var_auto);
+ body.emit(r0891);
+ ir_variable *const r0892 = new(mem_ctx) ir_variable(glsl_type::uint_type, "aSign", ir_var_auto);
+ body.emit(r0892);
+ ir_variable *const r0893 = new(mem_ctx) ir_variable(glsl_type::uint_type, "aFracHi", ir_var_auto);
+ body.emit(r0893);
+ ir_variable *const r0894 = body.make_temp(glsl_type::uint_type, "extractFloat64FracHi_retval");
+ body.emit(assign(r0894, bit_and(swizzle_y(r088E), body.constant(1048575u)), 0x01));
+
+ body.emit(assign(r0893, r0894, 0x01));
+
+ ir_variable *const r0895 = body.make_temp(glsl_type::int_type, "extractFloat64Exp_retval");
+ ir_expression *const r0896 = rshift(swizzle_y(r088E), body.constant(int(20)));
+ ir_expression *const r0897 = bit_and(r0896, body.constant(2047u));
+ body.emit(assign(r0895, expr(ir_unop_u2i, r0897), 0x01));
+
+ body.emit(assign(r0892, rshift(swizzle_y(r088E), body.constant(int(31))), 0x01));
+
+ body.emit(assign(r0891, body.constant(0u), 0x01));
+
+ ir_variable *const r0898 = body.make_temp(glsl_type::int_type, "assignment_tmp");
+ body.emit(assign(r0898, add(r0895, body.constant(int(-1043))), 0x01));
+
+ /* IF CONDITION */
+ ir_expression *const r089A = gequal(r0898, body.constant(int(0)));
+ ir_if *f0899 = new(mem_ctx) ir_if(operand(r089A).val);
+ exec_list *const f0899_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f0899->then_instructions;
+
+ /* IF CONDITION */
+ ir_expression *const r089C = less(body.constant(int(1054)), r0895);
+ ir_if *f089B = new(mem_ctx) ir_if(operand(r089C).val);
+ exec_list *const f089B_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f089B->then_instructions;
+
+ /* IF CONDITION */
+ ir_expression *const r089E = equal(r0895, body.constant(int(2047)));
+ ir_expression *const r089F = bit_or(r0894, swizzle_x(r088E));
+ ir_expression *const r08A0 = expr(ir_unop_u2i, r089F);
+ ir_expression *const r08A1 = expr(ir_unop_i2b, r08A0);
+ ir_expression *const r08A2 = logic_and(r089E, r08A1);
+ ir_if *f089D = new(mem_ctx) ir_if(operand(r08A2).val);
+ exec_list *const f089D_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f089D->then_instructions;
+
+ body.emit(assign(r0892, body.constant(0u), 0x01));
+
+
+ body.instructions = f089D_parent_instructions;
+ body.emit(f089D);
+
+ /* END IF */
+
+ ir_expression *const r08A3 = expr(ir_unop_u2i, r0892);
+ ir_expression *const r08A4 = expr(ir_unop_i2b, r08A3);
+ body.emit(assign(r0890, expr(ir_triop_csel, r08A4, body.constant(int(-2147483648)), body.constant(int(2147483647))), 0x01));
+
+ body.emit(assign(r088F, body.constant(false), 0x01));
+
+
+ /* ELSE INSTRUCTIONS */
+ body.instructions = &f089B->else_instructions;
+
+ ir_variable *const r08A5 = body.make_temp(glsl_type::uint_type, "a0");
+ body.emit(assign(r08A5, bit_or(r0894, body.constant(1048576u)), 0x01));
+
+ ir_expression *const r08A6 = equal(r0898, body.constant(int(0)));
+ ir_expression *const r08A7 = lshift(r08A5, r0898);
+ ir_expression *const r08A8 = neg(r0898);
+ ir_expression *const r08A9 = bit_and(r08A8, body.constant(int(31)));
+ ir_expression *const r08AA = rshift(swizzle_x(r088E), r08A9);
+ ir_expression *const r08AB = bit_or(r08A7, r08AA);
+ body.emit(assign(r0891, expr(ir_triop_csel, r08A6, r08A5, r08AB), 0x01));
+
+
+ body.instructions = f089B_parent_instructions;
+ body.emit(f089B);
+
+ /* END IF */
+
+
+ /* ELSE INSTRUCTIONS */
+ body.instructions = &f0899->else_instructions;
+
+ /* IF CONDITION */
+ ir_expression *const r08AD = less(r0895, body.constant(int(1023)));
+ ir_if *f08AC = new(mem_ctx) ir_if(operand(r08AD).val);
+ exec_list *const f08AC_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f08AC->then_instructions;
+
+ body.emit(assign(r0890, body.constant(int(0)), 0x01));
+
+ body.emit(assign(r088F, body.constant(false), 0x01));
+
+
+ /* ELSE INSTRUCTIONS */
+ body.instructions = &f08AC->else_instructions;
+
+ body.emit(assign(r0893, bit_or(r0894, body.constant(1048576u)), 0x01));
+
+ ir_expression *const r08AE = neg(r0898);
+ body.emit(assign(r0891, rshift(r0893, r08AE), 0x01));
+
+
+ body.instructions = f08AC_parent_instructions;
+ body.emit(f08AC);
+
+ /* END IF */
+
+
+ body.instructions = f0899_parent_instructions;
+ body.emit(f0899);
+
+ /* END IF */
+
+ /* IF CONDITION */
+ ir_if *f08AF = new(mem_ctx) ir_if(operand(r088F).val);
+ exec_list *const f08AF_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f08AF->then_instructions;
+
+ ir_variable *const r08B0 = body.make_temp(glsl_type::int_type, "mix_retval");
+ ir_expression *const r08B1 = nequal(r0892, body.constant(0u));
+ ir_expression *const r08B2 = expr(ir_unop_u2i, r0891);
+ ir_expression *const r08B3 = neg(r08B2);
+ ir_expression *const r08B4 = expr(ir_unop_u2i, r0891);
+ body.emit(assign(r08B0, expr(ir_triop_csel, r08B1, r08B3, r08B4), 0x01));
+
+ ir_expression *const r08B5 = less(r08B0, body.constant(int(0)));
+ ir_expression *const r08B6 = expr(ir_unop_b2i, r08B5);
+ ir_expression *const r08B7 = expr(ir_unop_i2u, r08B6);
+ ir_expression *const r08B8 = bit_xor(r0892, r08B7);
+ ir_expression *const r08B9 = expr(ir_unop_u2i, r08B8);
+ ir_expression *const r08BA = expr(ir_unop_i2b, r08B9);
+ ir_expression *const r08BB = expr(ir_unop_i2b, r08B0);
+ ir_expression *const r08BC = logic_and(r08BA, r08BB);
+ ir_expression *const r08BD = expr(ir_unop_u2i, r0892);
+ ir_expression *const r08BE = expr(ir_unop_i2b, r08BD);
+ ir_expression *const r08BF = expr(ir_triop_csel, r08BE, body.constant(int(-2147483648)), body.constant(int(2147483647)));
+ body.emit(assign(r0890, expr(ir_triop_csel, r08BC, r08BF, r08B0), 0x01));
+
+ body.emit(assign(r088F, body.constant(false), 0x01));
+
+
+ body.instructions = f08AF_parent_instructions;
+ body.emit(f08AF);
+
+ /* END IF */
+
+ body.emit(ret(r0890));
+
+ sig->replace_parameters(&sig_parameters);
+ return sig;
+}
diff --git a/src/compiler/glsl/builtin_functions.cpp b/src/compiler/glsl/builtin_functions.cpp
index 20051b1..96c3ff2 100644
--- a/src/compiler/glsl/builtin_functions.cpp
+++ b/src/compiler/glsl/builtin_functions.cpp
@@ -3378,6 +3378,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 a9674dc..8a7c914 100644
--- a/src/compiler/glsl/builtin_functions.h
+++ b/src/compiler/glsl/builtin_functions.h
@@ -94,6 +94,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 befaf29..557d773 100644
--- a/src/compiler/glsl/float64.glsl
+++ b/src/compiler/glsl/float64.glsl
@@ -812,3 +812,44 @@ 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 shiftCount = aExp - 0x413;
+
+ if (0 <= shiftCount) {
+ if (0x41E < aExp) {
+ if ((aExp == 0x7FF) && bool(aFracHi | aFracLo))
+ aSign = 0u;
+ return mix(0x7FFFFFFF, 0x80000000, bool(aSign));
+ }
+ shortShift64Left(aFracHi | 0x00100000u, aFracLo, shiftCount, absZ, aFracExtra);
+ } else {
+ if (aExp < 0x3FF)
+ return 0;
+
+ aFracHi |= 0x00100000u;
+ aFracExtra = ( aFracHi << (shiftCount & 31)) | aFracLo;
+ absZ = aFracHi >> (- shiftCount);
+ }
+
+ int z = mix(int(absZ), -int(absZ), (aSign != 0u));
+ int nan = mix(0x7FFFFFFF, 0x80000000, bool(aSign));
+ return mix(z, nan, bool(aSign ^ uint(z < 0)) && bool(z));
+}
diff --git a/src/compiler/glsl/glcpp/glcpp-parse.y b/src/compiler/glsl/glcpp/glcpp-parse.y
index 826ed01..3e3b6b7 100644
--- a/src/compiler/glsl/glcpp/glcpp-parse.y
+++ b/src/compiler/glsl/glcpp/glcpp-parse.y
@@ -2377,6 +2377,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.9.5
More information about the mesa-dev
mailing list