From: Elie Tournier <tournier.e...@gmail.com> v2: use mix
Signed-off-by: Elie Tournier <elie.tourn...@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev