From: Elie Tournier <tournier.e...@gmail.com> Signed-off-by: Elie Tournier <elie.tourn...@collabora.com> --- src/compiler/glsl/builtin_float64.h | 388 ++++++++++++++++++++++++++++++++ src/compiler/glsl/builtin_functions.cpp | 4 + src/compiler/glsl/builtin_functions.h | 3 + src/compiler/glsl/float64.glsl | 100 ++++++++ src/compiler/glsl/glcpp/glcpp-parse.y | 1 + 5 files changed, 496 insertions(+)
diff --git a/src/compiler/glsl/builtin_float64.h b/src/compiler/glsl/builtin_float64.h index b656fad..f937a2f 100644 --- a/src/compiler/glsl/builtin_float64.h +++ b/src/compiler/glsl/builtin_float64.h @@ -5662,3 +5662,391 @@ int_to_fp64(void *mem_ctx, builtin_available_predicate avail) sig->replace_parameters(&sig_parameters); return sig; } +ir_function_signature * +packFloat32(void *mem_ctx, builtin_available_predicate avail) +{ + ir_function_signature *const sig = + new(mem_ctx) ir_function_signature(glsl_type::float_type, avail); + ir_factory body(&sig->body, mem_ctx); + sig->is_defined = true; + + exec_list sig_parameters; + + ir_variable *const r08EC = new(mem_ctx) ir_variable(glsl_type::uint_type, "zSign", ir_var_function_in); + sig_parameters.push_tail(r08EC); + ir_variable *const r08ED = new(mem_ctx) ir_variable(glsl_type::int_type, "zExp", ir_var_function_in); + sig_parameters.push_tail(r08ED); + ir_variable *const r08EE = new(mem_ctx) ir_variable(glsl_type::uint_type, "zFrac", ir_var_function_in); + sig_parameters.push_tail(r08EE); + ir_variable *const r08EF = body.make_temp(glsl_type::float_type, "uintBitsToFloat_retval"); + ir_expression *const r08F0 = lshift(r08EC, body.constant(int(31))); + ir_expression *const r08F1 = expr(ir_unop_i2u, r08ED); + ir_expression *const r08F2 = lshift(r08F1, body.constant(int(23))); + ir_expression *const r08F3 = add(r08F0, r08F2); + ir_expression *const r08F4 = add(r08F3, r08EE); + body.emit(assign(r08EF, expr(ir_unop_bitcast_u2f, r08F4), 0x01)); + + body.emit(ret(r08EF)); + + sig->replace_parameters(&sig_parameters); + return sig; +} +ir_function_signature * +roundAndPackFloat32(void *mem_ctx, builtin_available_predicate avail) +{ + ir_function_signature *const sig = + new(mem_ctx) ir_function_signature(glsl_type::float_type, avail); + ir_factory body(&sig->body, mem_ctx); + sig->is_defined = true; + + exec_list sig_parameters; + + ir_variable *const r08F5 = new(mem_ctx) ir_variable(glsl_type::uint_type, "zSign", ir_var_function_in); + sig_parameters.push_tail(r08F5); + ir_variable *const r08F6 = new(mem_ctx) ir_variable(glsl_type::int_type, "zExp", ir_var_function_in); + sig_parameters.push_tail(r08F6); + ir_variable *const r08F7 = new(mem_ctx) ir_variable(glsl_type::uint_type, "zFrac", ir_var_function_in); + sig_parameters.push_tail(r08F7); + ir_variable *const r08F8 = body.make_temp(glsl_type::bool_type, "execute_flag"); + body.emit(assign(r08F8, body.constant(true), 0x01)); + + ir_variable *const r08F9 = body.make_temp(glsl_type::float_type, "return_value"); + ir_variable *const r08FA = new(mem_ctx) ir_variable(glsl_type::int_type, "roundBits", ir_var_auto); + body.emit(r08FA); + ir_expression *const r08FB = bit_and(r08F7, body.constant(127u)); + body.emit(assign(r08FA, expr(ir_unop_u2i, r08FB), 0x01)); + + /* IF CONDITION */ + ir_expression *const r08FD = expr(ir_unop_i2u, r08F6); + ir_expression *const r08FE = gequal(r08FD, body.constant(253u)); + ir_if *f08FC = new(mem_ctx) ir_if(operand(r08FE).val); + exec_list *const f08FC_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f08FC->then_instructions; + + /* IF CONDITION */ + ir_expression *const r0900 = less(body.constant(int(253)), r08F6); + ir_expression *const r0901 = equal(r08F6, body.constant(int(253))); + ir_expression *const r0902 = expr(ir_unop_u2i, r08F7); + ir_expression *const r0903 = less(r0902, body.constant(int(-64))); + ir_expression *const r0904 = logic_and(r0901, r0903); + ir_expression *const r0905 = logic_or(r0900, r0904); + ir_if *f08FF = new(mem_ctx) ir_if(operand(r0905).val); + exec_list *const f08FF_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f08FF->then_instructions; + + ir_expression *const r0906 = lshift(r08F5, body.constant(int(31))); + ir_expression *const r0907 = add(r0906, body.constant(2139095040u)); + body.emit(assign(r08F9, expr(ir_unop_bitcast_u2f, r0907), 0x01)); + + body.emit(assign(r08F8, body.constant(false), 0x01)); + + + /* ELSE INSTRUCTIONS */ + body.instructions = &f08FF->else_instructions; + + ir_variable *const r0908 = body.make_temp(glsl_type::int_type, "assignment_tmp"); + body.emit(assign(r0908, neg(r08F6), 0x01)); + + ir_variable *const r0909 = body.make_temp(glsl_type::bool_type, "assignment_tmp"); + body.emit(assign(r0909, less(r08F6, body.constant(int(0))), 0x01)); + + ir_variable *const r090A = body.make_temp(glsl_type::uint_type, "mix_retval"); + ir_expression *const r090B = neg(r08F6); + ir_expression *const r090C = less(r090B, body.constant(int(32))); + ir_expression *const r090D = rshift(r08F7, r0908); + ir_expression *const r090E = neg(r0908); + ir_expression *const r090F = bit_and(r090E, body.constant(int(31))); + ir_expression *const r0910 = lshift(r08F7, r090F); + ir_expression *const r0911 = nequal(r0910, body.constant(0u)); + ir_expression *const r0912 = expr(ir_unop_b2i, r0911); + ir_expression *const r0913 = expr(ir_unop_i2u, r0912); + ir_expression *const r0914 = bit_or(r090D, r0913); + ir_expression *const r0915 = nequal(r08F7, body.constant(0u)); + ir_expression *const r0916 = expr(ir_unop_b2i, r0915); + ir_expression *const r0917 = expr(ir_unop_i2u, r0916); + ir_expression *const r0918 = expr(ir_triop_csel, r090C, r0914, r0917); + body.emit(assign(r090A, expr(ir_triop_csel, r0909, r0918, r08F7), 0x01)); + + body.emit(assign(r08F7, r090A, 0x01)); + + ir_expression *const r0919 = expr(ir_unop_u2i, r090A); + ir_expression *const r091A = bit_and(r0919, body.constant(int(127))); + body.emit(assign(r08FA, expr(ir_triop_csel, r0909, r091A, r08FA), 0x01)); + + body.emit(assign(r08F6, expr(ir_triop_csel, r0909, body.constant(int(0)), r08F6), 0x01)); + + + body.instructions = f08FF_parent_instructions; + body.emit(f08FF); + + /* END IF */ + + + body.instructions = f08FC_parent_instructions; + body.emit(f08FC); + + /* END IF */ + + /* IF CONDITION */ + ir_if *f091B = new(mem_ctx) ir_if(operand(r08F8).val); + exec_list *const f091B_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f091B->then_instructions; + + ir_expression *const r091C = add(r08F7, body.constant(64u)); + body.emit(assign(r08F7, rshift(r091C, body.constant(int(7))), 0x01)); + + ir_expression *const r091D = bit_xor(r08FA, body.constant(int(64))); + ir_expression *const r091E = equal(r091D, body.constant(int(0))); + ir_expression *const r091F = expr(ir_unop_b2i, r091E); + ir_expression *const r0920 = expr(ir_unop_i2u, r091F); + ir_expression *const r0921 = expr(ir_unop_bit_not, r0920); + body.emit(assign(r08F7, bit_and(r08F7, r0921), 0x01)); + + ir_expression *const r0922 = lshift(r08F5, body.constant(int(31))); + ir_expression *const r0923 = equal(r08F7, body.constant(0u)); + ir_expression *const r0924 = expr(ir_triop_csel, r0923, body.constant(int(0)), r08F6); + ir_expression *const r0925 = expr(ir_unop_i2u, r0924); + ir_expression *const r0926 = lshift(r0925, body.constant(int(23))); + ir_expression *const r0927 = add(r0922, r0926); + ir_expression *const r0928 = add(r0927, r08F7); + body.emit(assign(r08F9, expr(ir_unop_bitcast_u2f, r0928), 0x01)); + + body.emit(assign(r08F8, body.constant(false), 0x01)); + + + body.instructions = f091B_parent_instructions; + body.emit(f091B); + + /* END IF */ + + body.emit(ret(r08F9)); + + sig->replace_parameters(&sig_parameters); + return sig; +} +ir_function_signature * +fp64_to_fp32(void *mem_ctx, builtin_available_predicate avail) +{ + ir_function_signature *const sig = + new(mem_ctx) ir_function_signature(glsl_type::float_type, avail); + ir_factory body(&sig->body, mem_ctx); + sig->is_defined = true; + + exec_list sig_parameters; + + ir_variable *const r0929 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "a", ir_var_function_in); + sig_parameters.push_tail(r0929); + ir_variable *const r092A = body.make_temp(glsl_type::float_type, "return_value"); + ir_variable *const r092B = body.make_temp(glsl_type::uint_type, "extractFloat64FracLo_retval"); + body.emit(assign(r092B, swizzle_x(r0929), 0x01)); + + ir_variable *const r092C = body.make_temp(glsl_type::uint_type, "extractFloat64FracHi_retval"); + body.emit(assign(r092C, bit_and(swizzle_y(r0929), body.constant(1048575u)), 0x01)); + + ir_variable *const r092D = body.make_temp(glsl_type::int_type, "extractFloat64Exp_retval"); + ir_expression *const r092E = rshift(swizzle_y(r0929), body.constant(int(20))); + ir_expression *const r092F = bit_and(r092E, body.constant(2047u)); + body.emit(assign(r092D, expr(ir_unop_u2i, r092F), 0x01)); + + ir_variable *const r0930 = body.make_temp(glsl_type::uint_type, "extractFloat64Sign_retval"); + body.emit(assign(r0930, rshift(swizzle_y(r0929), body.constant(int(31))), 0x01)); + + /* IF CONDITION */ + ir_expression *const r0932 = equal(r092D, body.constant(int(2047))); + ir_if *f0931 = new(mem_ctx) ir_if(operand(r0932).val); + exec_list *const f0931_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0931->then_instructions; + + ir_variable *const r0933 = new(mem_ctx) ir_variable(glsl_type::float_type, "rval", ir_var_auto); + body.emit(r0933); + ir_variable *const r0934 = body.make_temp(glsl_type::uint_type, "z1Ptr"); + body.emit(assign(r0934, lshift(swizzle_x(r0929), body.constant(int(12))), 0x01)); + + ir_expression *const r0935 = lshift(swizzle_y(r0929), body.constant(int(12))); + ir_expression *const r0936 = rshift(swizzle_x(r0929), body.constant(int(20))); + body.emit(assign(r0929, bit_or(r0935, r0936), 0x02)); + + body.emit(assign(r0929, r0934, 0x01)); + + ir_expression *const r0937 = lshift(r0930, body.constant(int(31))); + ir_expression *const r0938 = bit_or(r0937, body.constant(2143289344u)); + ir_expression *const r0939 = rshift(swizzle_y(r0929), body.constant(int(9))); + ir_expression *const r093A = bit_or(r0938, r0939); + body.emit(assign(r0933, expr(ir_unop_bitcast_u2f, r093A), 0x01)); + + ir_variable *const r093B = body.make_temp(glsl_type::float_type, "mix_retval"); + ir_expression *const r093C = bit_or(r092C, r092B); + ir_expression *const r093D = nequal(r093C, body.constant(0u)); + ir_expression *const r093E = lshift(r0930, body.constant(int(31))); + ir_expression *const r093F = add(r093E, body.constant(2139095040u)); + ir_expression *const r0940 = expr(ir_unop_bitcast_u2f, r093F); + body.emit(assign(r093B, expr(ir_triop_csel, r093D, r0933, r0940), 0x01)); + + body.emit(assign(r0933, r093B, 0x01)); + + body.emit(assign(r092A, r093B, 0x01)); + + + /* ELSE INSTRUCTIONS */ + body.instructions = &f0931->else_instructions; + + ir_variable *const r0941 = body.make_temp(glsl_type::uint_type, "mix_retval"); + ir_expression *const r0942 = lshift(r092C, body.constant(int(10))); + ir_expression *const r0943 = rshift(r092B, body.constant(int(22))); + ir_expression *const r0944 = bit_or(r0942, r0943); + ir_expression *const r0945 = lshift(r092B, body.constant(int(10))); + ir_expression *const r0946 = nequal(r0945, body.constant(0u)); + ir_expression *const r0947 = expr(ir_unop_b2i, r0946); + ir_expression *const r0948 = expr(ir_unop_i2u, r0947); + body.emit(assign(r0941, bit_or(r0944, r0948), 0x01)); + + ir_variable *const r0949 = body.make_temp(glsl_type::uint_type, "mix_retval"); + ir_expression *const r094A = nequal(r092D, body.constant(int(0))); + ir_expression *const r094B = bit_or(r0941, body.constant(1073741824u)); + body.emit(assign(r0949, expr(ir_triop_csel, r094A, r094B, r0941), 0x01)); + + ir_variable *const r094C = body.make_temp(glsl_type::int_type, "zExp"); + body.emit(assign(r094C, add(r092D, body.constant(int(-897))), 0x01)); + + ir_variable *const r094D = body.make_temp(glsl_type::uint_type, "zFrac"); + body.emit(assign(r094D, r0949, 0x01)); + + ir_variable *const r094E = body.make_temp(glsl_type::bool_type, "execute_flag"); + body.emit(assign(r094E, body.constant(true), 0x01)); + + ir_variable *const r094F = body.make_temp(glsl_type::float_type, "return_value"); + ir_variable *const r0950 = new(mem_ctx) ir_variable(glsl_type::int_type, "roundBits", ir_var_auto); + body.emit(r0950); + ir_expression *const r0951 = bit_and(r0949, body.constant(127u)); + body.emit(assign(r0950, expr(ir_unop_u2i, r0951), 0x01)); + + /* IF CONDITION */ + ir_expression *const r0953 = expr(ir_unop_i2u, r094C); + ir_expression *const r0954 = gequal(r0953, body.constant(253u)); + ir_if *f0952 = new(mem_ctx) ir_if(operand(r0954).val); + exec_list *const f0952_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0952->then_instructions; + + /* IF CONDITION */ + ir_expression *const r0956 = less(body.constant(int(253)), r094C); + ir_expression *const r0957 = equal(r094C, body.constant(int(253))); + ir_expression *const r0958 = expr(ir_unop_u2i, r0949); + ir_expression *const r0959 = less(r0958, body.constant(int(-64))); + ir_expression *const r095A = logic_and(r0957, r0959); + ir_expression *const r095B = logic_or(r0956, r095A); + ir_if *f0955 = new(mem_ctx) ir_if(operand(r095B).val); + exec_list *const f0955_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0955->then_instructions; + + ir_expression *const r095C = lshift(r0930, body.constant(int(31))); + ir_expression *const r095D = add(r095C, body.constant(2139095040u)); + body.emit(assign(r094F, expr(ir_unop_bitcast_u2f, r095D), 0x01)); + + body.emit(assign(r094E, body.constant(false), 0x01)); + + + /* ELSE INSTRUCTIONS */ + body.instructions = &f0955->else_instructions; + + ir_variable *const r095E = body.make_temp(glsl_type::int_type, "assignment_tmp"); + body.emit(assign(r095E, neg(r094C), 0x01)); + + ir_variable *const r095F = body.make_temp(glsl_type::bool_type, "assignment_tmp"); + body.emit(assign(r095F, less(r094C, body.constant(int(0))), 0x01)); + + ir_variable *const r0960 = body.make_temp(glsl_type::uint_type, "mix_retval"); + ir_expression *const r0961 = neg(r094C); + ir_expression *const r0962 = less(r0961, body.constant(int(32))); + ir_expression *const r0963 = rshift(r0949, r095E); + ir_expression *const r0964 = neg(r095E); + ir_expression *const r0965 = bit_and(r0964, body.constant(int(31))); + ir_expression *const r0966 = lshift(r0949, r0965); + ir_expression *const r0967 = nequal(r0966, body.constant(0u)); + ir_expression *const r0968 = expr(ir_unop_b2i, r0967); + ir_expression *const r0969 = expr(ir_unop_i2u, r0968); + ir_expression *const r096A = bit_or(r0963, r0969); + ir_expression *const r096B = nequal(r0949, body.constant(0u)); + ir_expression *const r096C = expr(ir_unop_b2i, r096B); + ir_expression *const r096D = expr(ir_unop_i2u, r096C); + ir_expression *const r096E = expr(ir_triop_csel, r0962, r096A, r096D); + body.emit(assign(r0960, expr(ir_triop_csel, r095F, r096E, r0949), 0x01)); + + body.emit(assign(r094D, r0960, 0x01)); + + ir_expression *const r096F = expr(ir_unop_u2i, r0960); + ir_expression *const r0970 = bit_and(r096F, body.constant(int(127))); + body.emit(assign(r0950, expr(ir_triop_csel, r095F, r0970, r0950), 0x01)); + + body.emit(assign(r094C, expr(ir_triop_csel, r095F, body.constant(int(0)), r094C), 0x01)); + + + body.instructions = f0955_parent_instructions; + body.emit(f0955); + + /* END IF */ + + + body.instructions = f0952_parent_instructions; + body.emit(f0952); + + /* END IF */ + + /* IF CONDITION */ + ir_if *f0971 = new(mem_ctx) ir_if(operand(r094E).val); + exec_list *const f0971_parent_instructions = body.instructions; + + /* THEN INSTRUCTIONS */ + body.instructions = &f0971->then_instructions; + + ir_expression *const r0972 = add(r094D, body.constant(64u)); + body.emit(assign(r094D, rshift(r0972, body.constant(int(7))), 0x01)); + + ir_expression *const r0973 = bit_xor(r0950, body.constant(int(64))); + ir_expression *const r0974 = equal(r0973, body.constant(int(0))); + ir_expression *const r0975 = expr(ir_unop_b2i, r0974); + ir_expression *const r0976 = expr(ir_unop_i2u, r0975); + ir_expression *const r0977 = expr(ir_unop_bit_not, r0976); + body.emit(assign(r094D, bit_and(r094D, r0977), 0x01)); + + ir_expression *const r0978 = lshift(r0930, body.constant(int(31))); + ir_expression *const r0979 = equal(r094D, body.constant(0u)); + ir_expression *const r097A = expr(ir_triop_csel, r0979, body.constant(int(0)), r094C); + ir_expression *const r097B = expr(ir_unop_i2u, r097A); + ir_expression *const r097C = lshift(r097B, body.constant(int(23))); + ir_expression *const r097D = add(r0978, r097C); + ir_expression *const r097E = add(r097D, r094D); + body.emit(assign(r094F, expr(ir_unop_bitcast_u2f, r097E), 0x01)); + + body.emit(assign(r094E, body.constant(false), 0x01)); + + + body.instructions = f0971_parent_instructions; + body.emit(f0971); + + /* END IF */ + + body.emit(assign(r092A, r094F, 0x01)); + + + body.instructions = f0931_parent_instructions; + body.emit(f0931); + + /* END IF */ + + body.emit(ret(r092A)); + + sig->replace_parameters(&sig_parameters); + return sig; +} diff --git a/src/compiler/glsl/builtin_functions.cpp b/src/compiler/glsl/builtin_functions.cpp index 3c4c8db..b0aa2e3 100644 --- a/src/compiler/glsl/builtin_functions.cpp +++ b/src/compiler/glsl/builtin_functions.cpp @@ -3386,6 +3386,10 @@ builtin_builder::create_builtins() generate_ir::int_to_fp64(mem_ctx, integer_functions_supported), NULL); + add_function("__builtin_fp64_to_fp32", + generate_ir::fp64_to_fp32(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 54055e1..a6e2192 100644 --- a/src/compiler/glsl/builtin_functions.h +++ b/src/compiler/glsl/builtin_functions.h @@ -100,6 +100,9 @@ fp64_to_int(void *mem_ctx, builtin_available_predicate avail); ir_function_signature * int_to_fp64(void *mem_ctx, builtin_available_predicate avail); +ir_function_signature * +fp64_to_fp32(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 fcc58c1..ec6b80c 100644 --- a/src/compiler/glsl/float64.glsl +++ b/src/compiler/glsl/float64.glsl @@ -876,3 +876,103 @@ int_to_fp64(int a) } return packFloat64(zSign, 0x412 - shiftCount, zFrac0, zFrac1); } + +/* Packs the sign `zSign', exponent `zExp', and significand `zFrac' into a + * single-precision floating-point value, returning the result. After being + * shifted into the proper positions, the three fields are simply added + * together to form the result. This means that any integer portion of `zSig' + * will be added into the exponent. Since a properly normalized significand + * will have an integer portion equal to 1, the `zExp' input should be 1 less + * than the desired result exponent whenever `zFrac' is a complete, normalized + * significand. + */ +float +packFloat32(uint zSign, int zExp, uint zFrac) +{ + return uintBitsToFloat((zSign<<31) + (uint(zExp)<<23) + zFrac); +} + +/* Takes an abstract floating-point value having sign `zSign', exponent `zExp', + * and significand `zFrac', and returns the proper single-precision floating- + * point value corresponding to the abstract input. Ordinarily, the abstract + * value is simply rounded and packed into the single-precision format, with + * the inexact exception raised if the abstract input cannot be represented + * exactly. However, if the abstract value is too large, the overflow and + * inexact exceptions are raised and an infinity or maximal finite value is + * returned. If the abstract value is too small, the input value is rounded to + * a subnormal number, and the underflow and inexact exceptions are raised if + * the abstract input cannot be represented exactly as a subnormal single- + * precision floating-point number. + * The input significand `zFrac' has its binary point between bits 30 + * and 29, which is 7 bits to the left of the usual location. This shifted + * significand must be normalized or smaller. If `zFrac' is not normalized, + * `zExp' must be 0; in that case, the result returned is a subnormal number, + * and it must not require rounding. In the usual case that `zFrac' is + * normalized, `zExp' must be 1 less than the "true" floating-point exponent. + * The handling of underflow and overflow follows the IEEE Standard for + * Floating-Point Arithmetic. + */ +float +roundAndPackFloat32(uint zSign, int zExp, uint zFrac) +{ + bool roundNearestEven; + int roundIncrement; + int roundBits; + + roundNearestEven = FLOAT_ROUNDING_MODE == FLOAT_ROUND_NEAREST_EVEN; + roundIncrement = 0x40; + if (!roundNearestEven) { + if (FLOAT_ROUNDING_MODE == FLOAT_ROUND_TO_ZERO) { + roundIncrement = 0; + } else { + roundIncrement = 0x7F; + if (zSign != 0u) { + if (FLOAT_ROUNDING_MODE == FLOAT_ROUND_UP) + roundIncrement = 0; + } else { + if (FLOAT_ROUNDING_MODE == FLOAT_ROUND_DOWN) + roundIncrement = 0; + } + } + } + roundBits = int(zFrac & 0x7Fu); + if (0xFDu <= uint(zExp)) { + if ((0xFD < zExp) || ((zExp == 0xFD) && (int(zFrac) + roundIncrement) < 0)) + return packFloat32(zSign, 0xFF, 0u) - float(roundIncrement == 0); + int count = -zExp; + bool zexp_lt0 = zExp < 0; + uint zFrac_lt0 = mix(uint(zFrac != 0u), (zFrac>>count) | uint((zFrac<<((-count) & 31)) != 0u), (-zExp) < 32); + zFrac = mix(zFrac, zFrac_lt0, zexp_lt0); + roundBits = mix(roundBits, int(zFrac) & 0x7f, zexp_lt0); + zExp = mix(zExp, 0, zexp_lt0); + } + zFrac = (zFrac + uint(roundIncrement))>>7; + zFrac &= ~uint(((roundBits ^ 0x40) == 0) && roundNearestEven); + + return packFloat32(zSign, mix(zExp, 0, zFrac == 0u), zFrac); +} + +/* Returns the result of converting the double-precision floating-point value + * `a' to the single-precision floating-point format. The conversion is + * performed according to the IEEE Standard for Floating-Point Arithmetic. + */ +float +fp64_to_fp32(uvec2 a) +{ + uint zFrac = 0u; + uint allZero = 0u; + + uint aFracLo = extractFloat64FracLo(a); + uint aFracHi = extractFloat64FracHi(a); + int aExp = extractFloat64Exp(a); + uint aSign = extractFloat64Sign(a); + if (aExp == 0x7FF) { + shortShift64Left(a.y, a.x, 12, a.y, a.x); + float rval = uintBitsToFloat((aSign<<31) | 0x7FC00000u | (a.y>>9)); + rval = mix(packFloat32(aSign, 0xFF, 0u), rval, (aFracHi | aFracLo) != 0u); + return rval; + } + shift64RightJamming(aFracHi, aFracLo, 22, allZero, zFrac); + zFrac = mix(zFrac, zFrac | 0x40000000u, aExp != 0); + return roundAndPackFloat32(aSign, aExp - 0x381, zFrac); +} diff --git a/src/compiler/glsl/glcpp/glcpp-parse.y b/src/compiler/glsl/glcpp/glcpp-parse.y index 2c2d2ea..bc85026 100644 --- a/src/compiler/glsl/glcpp/glcpp-parse.y +++ b/src/compiler/glsl/glcpp/glcpp-parse.y @@ -2379,6 +2379,7 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio add_builtin_define(parser, "__have_builtin_builtin_uint_to_fp64", 1); add_builtin_define(parser, "__have_builtin_builtin_fp64_to_int", 1); add_builtin_define(parser, "__have_builtin_builtin_int_to_fp64", 1); + add_builtin_define(parser, "__have_builtin_builtin_fp64_to_fp32", 1); } } -- 2.9.5 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev