summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Krol <michal@vmware.com>2010-03-31 21:54:54 +0200
committerMichal Krol <michal@vmware.com>2010-03-31 21:55:31 +0200
commitb8012643e1f5f6e49593ec8f04d3721df53e6afb (patch)
treef7f6948c6d5910ad1425600bf0cfd874235f4032
parent329814c6ee8a87d67a55ecf197af9d6e6fb7ade0 (diff)
util: First stab at half-float conversion.
-rw-r--r--src/gallium/auxiliary/util/u_format_pack.py101
1 files changed, 55 insertions, 46 deletions
diff --git a/src/gallium/auxiliary/util/u_format_pack.py b/src/gallium/auxiliary/util/u_format_pack.py
index c74900ce63..26f8748604 100644
--- a/src/gallium/auxiliary/util/u_format_pack.py
+++ b/src/gallium/auxiliary/util/u_format_pack.py
@@ -43,6 +43,45 @@ import math
from u_format_parse import *
+def generate_f16_to_f32():
+ '''Naive implementation, need something faster that operates on bits'''
+
+ print '''
+static float
+f16_to_f32(uint16_t h)
+{
+ unsigned mantissa = h & 0x3ff;
+ unsigned exponent = (h >> 10) & 0x1f;
+ float sign = (h & 0x8000) ? -1.0f : 1.0f;
+
+ if (exponent == 0) {
+ if (mantissa == 0) {
+ return sign * 0.0f;
+ }
+ return sign * powf(2.0f, -14.0f) * (float)mantissa / 1024.0f;
+ }
+ if (exponent == 31) {
+ if (mantissa == 0) {
+ /* XXX: infinity */
+ return sign * 100000.0f;
+ }
+ /* XXX: NaN */
+ return 1000.0f;
+ }
+ return sign * powf(2.0f, (float)exponent - 15.0f) * (1.0f + (float)mantissa / 1024.0f);
+}
+'''
+
+def generate_f32_to_f16():
+ print '''
+static uint16_t
+f32_to_f16(float f)
+{
+ /* TODO */
+ return 0;
+}
+'''
+
def generate_format_type(format):
'''Generate a structure that describes the format.'''
@@ -127,9 +166,6 @@ def is_format_supported(format):
channel = format.channels[i]
if channel.type not in (VOID, UNSIGNED, SIGNED, FLOAT):
return False
- if channel.type == FLOAT:
- if channel.size not in (32, 64):
- return False
# We can only read a color from a depth/stencil format if the depth channel is present
if format.colorspace == 'zs' and format.swizzles[0] == SWIZZLE_NONE:
@@ -153,7 +189,9 @@ def native_type(format):
elif channel.type == SIGNED:
return 'int%u_t' % channel.size
elif channel.type == FLOAT:
- if channel.size == 32:
+ if channel.size == 16:
+ return 'uint16_t'
+ elif channel.size == 32:
return 'float'
elif channel.size == 64:
return 'double'
@@ -202,31 +240,6 @@ def get_one(type):
return (1 << get_one_shift(type)) - 1
-def generate_clamp():
- '''Code generate the clamping functions for each type.
-
- We don't use a macro so that arguments with side effects,
- like *src_pixel++ are correctly handled.
- '''
-
- for suffix, native_type in [
- ('', 'double'),
- ('f', 'float'),
- ('ui', 'unsigned int'),
- ('si', 'int'),
- ]:
- print 'static INLINE %s' % native_type
- print 'clamp%s(%s value, %s lbound, %s ubound)' % (suffix, native_type, native_type, native_type)
- print '{'
- print ' if(value < lbound)'
- print ' return lbound;'
- print ' if(value > ubound)'
- print ' return ubound;'
- print ' return value;'
- print '}'
- print
-
-
def clamp_expr(src_channel, dst_channel, dst_native_type, value):
'''Generate the expression to clamp the value in the source type to the
destination type range.'''
@@ -234,21 +247,6 @@ def clamp_expr(src_channel, dst_channel, dst_native_type, value):
if src_channel == dst_channel:
return value
- # Pick the approriate clamp function
- if src_channel.type == FLOAT:
- if src_channel.size == 32:
- func = 'clampf'
- elif src_channel.size == 64:
- func = 'clamp'
- else:
- assert False
- elif src_channel.type == UNSIGNED:
- func = 'clampui'
- elif src_channel.type == SIGNED:
- func = 'clampsi'
- else:
- assert False
-
src_min = src_channel.min()
src_max = src_channel.max()
dst_min = dst_channel.min()
@@ -273,7 +271,17 @@ def conversion_expr(src_channel, dst_channel, dst_native_type, value, clamp=True
return value
if src_channel.type == FLOAT and dst_channel.type == FLOAT:
- return '(%s)%s' % (dst_native_type, value)
+ if src_channel.size == dst_channel.size:
+ return value
+ if src_channel.size == 64:
+ value = '(float)%s' % (value)
+ elif src_channel.size == 16:
+ value = 'f16_to_f32(%s)' % (value)
+ if dst_channel.size == 16:
+ value = 'f32_to_f16(%s)' % (value)
+ elif dst_channel.size == 64:
+ value = '(double)%s' % (value)
+ return value
if clamp:
value = clamp_expr(src_channel, dst_channel, dst_native_type, value)
@@ -562,7 +570,8 @@ def generate(formats):
print '#include "u_format.h"'
print
- generate_clamp()
+ generate_f16_to_f32()
+ generate_f32_to_f16()
for format in formats:
if is_format_supported(format):