[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