summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Krol <[email protected]>2010-04-01 13:56:03 +0200
committerMichal Krol <[email protected]>2010-04-01 13:56:03 +0200
commit943408533d2ccbb3743dcbdf143f1d23d23f29a9 (patch)
tree95e58b42a0b8f2cfb439811d6fc1d022fb294f60
parentb7bca4b28cb5b12bc84391c53ea932cfd117dc52 (diff)
util: Generate correct format conversions for half floats.
-rw-r--r--src/gallium/auxiliary/util/u_format_pack.py98
1 files changed, 59 insertions, 39 deletions
diff --git a/src/gallium/auxiliary/util/u_format_pack.py b/src/gallium/auxiliary/util/u_format_pack.py
index d36c6377380..390be0c3b20 100644
--- a/src/gallium/auxiliary/util/u_format_pack.py
+++ b/src/gallium/auxiliary/util/u_format_pack.py
@@ -231,66 +231,86 @@ def conversion_expr(src_channel, dst_channel, dst_native_type, value, clamp=True
if src_channel == dst_channel:
return value
- if src_channel.type == FLOAT and dst_channel.type == FLOAT:
- if src_channel.size == 64:
- value = '(float)%s' % (value)
- elif src_channel.size == 16:
- value = 'util_half_to_float(%s)' % (value)
+ src_type = src_channel.type
+ src_size = src_channel.size
+ src_norm = src_channel.norm
- if dst_channel.size == 16:
- value = 'util_float_to_half(%s)' % (value)
- elif dst_channel.size == 64:
- value = '(double)%s' % (value)
-
- return value
+ # Promote half to float
+ if src_type == FLOAT and src_size == 16:
+ value = 'util_half_to_float(%s)' % value
+ src_size = 32
if clamp:
- value = clamp_expr(src_channel, dst_channel, dst_native_type, value)
-
- if dst_channel.type == FLOAT:
- if src_channel.norm:
- one = get_one(src_channel)
- if src_channel.size <= 23:
- scale = '(1.0f/0x%x)' % one
- else:
- # bigger than single precision mantissa, use double
- scale = '(1.0/0x%x)' % one
- value = '(%s * %s)' % (value, scale)
- return '(%s)%s' % (dst_native_type, value)
-
- if src_channel.type == FLOAT:
- if dst_channel.norm:
- dst_one = get_one(dst_channel)
- if dst_channel.size <= 23:
- scale = '0x%x' % dst_one
- else:
- # bigger than single precision mantissa, use double
- scale = '(double)0x%x' % dst_one
- value = '(%s * %s)' % (value, scale)
- return '(%s)%s' % (dst_native_type, value)
+ if dst_channel.type != FLOAT or src_type != FLOAT:
+ value = clamp_expr(src_channel, dst_channel, dst_native_type, value)
- if src_channel.type in (SIGNED, UNSIGNED) and dst_channel.type in (SIGNED, UNSIGNED):
- if not src_channel.norm and not dst_channel.norm:
+ if src_type in (SIGNED, UNSIGNED) and dst_channel.type in (SIGNED, UNSIGNED):
+ if not src_norm and not dst_channel.norm:
# neither is normalized -- just cast
return '(%s)%s' % (dst_native_type, value)
src_one = get_one(src_channel)
dst_one = get_one(dst_channel)
- if src_one > dst_one and src_channel.norm and dst_channel.norm:
+ if src_one > dst_one and src_norm and dst_channel.norm:
# We can just bitshift
src_shift = get_one_shift(src_channel)
dst_shift = get_one_shift(dst_channel)
value = '(%s >> %s)' % (value, src_shift - dst_shift)
else:
# We need to rescale using an intermediate type big enough to hold the multiplication of both
- tmp_native_type = intermediate_native_type(src_channel.size + dst_channel.size, src_channel.sign and dst_channel.sign)
+ tmp_native_type = intermediate_native_type(src_size + dst_channel.size, src_channel.sign and dst_channel.sign)
value = '((%s)%s)' % (tmp_native_type, value)
value = '(%s * 0x%x / 0x%x)' % (value, dst_one, src_one)
value = '(%s)%s' % (dst_native_type, value)
return value
- assert False
+ # Promote to either float or double
+ if src_type != FLOAT:
+ if src_norm:
+ one = get_one(src_channel)
+ if src_size <= 23:
+ value = '(%s * (1.0f/0x%x))' % (value, one)
+ if dst_channel.size <= 32:
+ value = '(float)%s' % value
+ src_size = 32
+ else:
+ # bigger than single precision mantissa, use double
+ value = '(%s * (1.0/0x%x))' % (value, one)
+ src_size = 64
+ src_norm = False
+ else:
+ if src_size <= 23 or dst_channel.size <= 32:
+ value = '(float)%s' % value
+ src_size = 32
+ else:
+ # bigger than single precision mantissa, use double
+ value = '(double)%s' % value
+ src_size = 64
+ src_type = FLOAT
+
+ # Convert double or float to non-float
+ if dst_channel.type != FLOAT:
+ if dst_channel.norm:
+ dst_one = get_one(dst_channel)
+ if dst_channel.size <= 23:
+ value = '(%s * 0x%x)' % (value, dst_one)
+ else:
+ # bigger than single precision mantissa, use double
+ value = '(%s * (double)0x%x)' % (value, dst_one)
+ value = '(%s)%s' % (dst_native_type, value)
+ else:
+ # Cast double to float when converting to either half or float
+ if dst_channel.size <= 32 and src_size > 32:
+ value = '(float)%s' % value
+ src_size = 32
+
+ if dst_channel.size == 16:
+ value = 'util_float_to_half(%s)' % value
+ elif dst_channel.size == 64 and src_size < 64:
+ value = '(double)%s' % value
+
+ return value
def generate_unpack_kernel(format, dst_channel, dst_native_type):