[Mesa-dev] [PATCH 13/50] glsl: Add "built-in" functions to do fp64_to_fp32(fp64)
Dave Airlie
airlied at gmail.com
Tue Mar 13 04:24:38 UTC 2018
From: Elie Tournier <tournier.elie at gmail.com>
Signed-off-by: Elie Tournier <elie.tournier at 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
More information about the mesa-dev
mailing list