llvmpipe: Do unswizzling in parallel when flushing for transfers.
[mesa.git] / src / gallium / drivers / llvmpipe / lp_tile_soa.py
index dc44d67d63422613123c2187e3d3bb845ef1947c..5ab63cbac67fdc190150292e42e9967f14f349e8 100644 (file)
@@ -42,7 +42,29 @@ import os.path
 
 sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), '../../auxiliary/util'))
 
-from u_format_access import *
+from u_format_pack import *
+
+
+def is_format_supported(format):
+    '''Determines whether we actually have the plumbing necessary to generate the 
+    to read/write to/from this format.'''
+
+    # FIXME: Ideally we would support any format combination here.
+
+    if format.layout != PLAIN:
+        return False
+
+    for i in range(4):
+        channel = format.channels[i]
+        if channel.type not in (VOID, UNSIGNED, SIGNED, FLOAT):
+            return False
+        if channel.type == FLOAT and channel.size not in (16, 32 ,64):
+            return False
+
+    if format.colorspace not in ('rgb', 'srgb'):
+        return False
+
+    return True
 
 
 def generate_format_read(format, dst_channel, dst_native_type, dst_suffix):
@@ -53,7 +75,7 @@ def generate_format_read(format, dst_channel, dst_native_type, dst_suffix):
     src_native_type = native_type(format)
 
     print 'static void'
-    print 'lp_tile_%s_read_%s(%s *dst, const uint8_t *src, unsigned src_stride, unsigned x0, unsigned y0, unsigned w, unsigned h)' % (name, dst_suffix, dst_native_type)
+    print 'lp_tile_%s_swizzle_%s(%s *dst, const uint8_t *src, unsigned src_stride, unsigned x0, unsigned y0, unsigned w, unsigned h)' % (name, dst_suffix, dst_native_type)
     print '{'
     print '   unsigned x, y;'
     print '   const uint8_t *src_row = src + y0*src_stride;'
@@ -62,7 +84,7 @@ def generate_format_read(format, dst_channel, dst_native_type, dst_suffix):
     print '      for (x = 0; x < w; ++x) {'
 
     names = ['']*4
-    if format.colorspace == 'rgb':
+    if format.colorspace in ('rgb', 'srgb'):
         for i in range(4):
             swizzle = format.swizzles[i]
             if swizzle < 4:
@@ -90,21 +112,26 @@ def generate_format_read(format, dst_channel, dst_native_type, dst_suffix):
                         value = '(%s >> %u)' % (value, shift)
                     if shift + width < format.block_size():
                         value = '(%s & 0x%x)' % (value, mask)
-                    value = conversion_expr(src_channel, dst_channel, dst_native_type, value)
+                    value = conversion_expr(src_channel, dst_channel, dst_native_type, value, clamp=False)
                     print '         %s %s = %s;' % (dst_native_type, names[i], value)
                 shift += width
         else:
+            for i in range(4):
+                if names[i]:
+                    print '         %s %s;' % (dst_native_type, names[i])
             for i in range(4):
                 src_channel = format.channels[i]
                 if names[i]:
                     value = '(*src_pixel++)'
-                    value = conversion_expr(src_channel, dst_channel, dst_native_type, value)
-                    print '         %s %s = %s;' % (dst_native_type, names[i], value)
+                    value = conversion_expr(src_channel, dst_channel, dst_native_type, value, clamp=False)
+                    print '         %s = %s;' % (names[i], value)
+                elif src_channel.size:
+                    print '         ++src_pixel;'
     else:
         assert False
 
     for i in range(4):
-        if format.colorspace == 'rgb':
+        if format.colorspace in ('rgb', 'srgb'):
             swizzle = format.swizzles[i]
             if swizzle < 4:
                 value = names[swizzle]
@@ -134,7 +161,7 @@ def pack_rgba(format, src_channel, r, g, b, a):
     """Return an expression for packing r, g, b, a into a pixel of the
     given format.  Ex: '(b << 24) | (g << 16) | (r << 8) | (a << 0)'
     """
-    assert format.colorspace == 'rgb'
+    assert format.colorspace in ('rgb', 'srgb')
     inv_swizzle = format.inv_swizzles()
     shift = 0
     expr = None
@@ -154,7 +181,7 @@ def pack_rgba(format, src_channel, r, g, b, a):
         if value:
             dst_channel = format.channels[i]
             dst_native_type = native_type(format)
-            value = conversion_expr(src_channel, dst_channel, dst_native_type, value)
+            value = conversion_expr(src_channel, dst_channel, dst_native_type, value, clamp=False)
             term = "((%s) << %d)" % (value, shift)
             if expr:
                 expr = expr + " | " + term
@@ -166,7 +193,7 @@ def pack_rgba(format, src_channel, r, g, b, a):
     return expr
 
 
-def emit_unrolled_write_code(format, src_channel):
+def emit_unrolled_unswizzle_code(format, src_channel):
     '''Emit code for writing a block based on unrolled loops.
     This is considerably faster than the TILE_PIXEL-based code below.
     '''
@@ -196,7 +223,7 @@ def emit_unrolled_write_code(format, src_channel):
     print '   }'
 
 
-def emit_tile_pixel_write_code(format, src_channel):
+def emit_tile_pixel_unswizzle_code(format, src_channel):
     '''Emit code for writing a block based on the TILE_PIXEL macro.'''
     dst_native_type = native_type(format)
 
@@ -217,7 +244,7 @@ def emit_tile_pixel_write_code(format, src_channel):
                 width = dst_channel.size
                 if inv_swizzle[i] is not None:
                     value = 'TILE_PIXEL(src, x, y, %u)' % inv_swizzle[i]
-                    value = conversion_expr(src_channel, dst_channel, dst_native_type, value)
+                    value = conversion_expr(src_channel, dst_channel, dst_native_type, value, clamp=False)
                     if shift:
                         value = '(%s << %u)' % (value, shift)
                     print '         pixel |= %s;' % value
@@ -228,8 +255,10 @@ def emit_tile_pixel_write_code(format, src_channel):
                 dst_channel = format.channels[i]
                 if inv_swizzle[i] is not None:
                     value = 'TILE_PIXEL(src, x, y, %u)' % inv_swizzle[i]
-                    value = conversion_expr(src_channel, dst_channel, dst_native_type, value)
+                    value = conversion_expr(src_channel, dst_channel, dst_native_type, value, clamp=False)
                     print '         *dst_pixel++ = %s;' % value
+                elif dst_channel.size:
+                    print '         ++dst_pixel;'
     else:
         assert False
 
@@ -244,22 +273,23 @@ def generate_format_write(format, src_channel, src_native_type, src_suffix):
     name = format.short_name()
 
     print 'static void'
-    print 'lp_tile_%s_write_%s(const %s *src, uint8_t *dst, unsigned dst_stride, unsigned x0, unsigned y0, unsigned w, unsigned h)' % (name, src_suffix, src_native_type)
+    print 'lp_tile_%s_unswizzle_%s(const %s *src, uint8_t *dst, unsigned dst_stride, unsigned x0, unsigned y0, unsigned w, unsigned h)' % (name, src_suffix, src_native_type)
     print '{'
     if format.layout == PLAIN \
         and format.colorspace == 'rgb' \
         and format.block_size() <= 32 \
         and format.is_pot() \
         and not format.is_mixed() \
-        and format.channels[0].type == UNSIGNED:
-        emit_unrolled_write_code(format, src_channel)
+        and (format.channels[0].type == UNSIGNED \
+             or format.channels[1].type == UNSIGNED):
+        emit_unrolled_unswizzle_code(format, src_channel)
     else:
-        emit_tile_pixel_write_code(format, src_channel)
+        emit_tile_pixel_unswizzle_code(format, src_channel)
     print '}'
     print
     
 
-def generate_read(formats, dst_channel, dst_native_type, dst_suffix):
+def generate_swizzle(formats, dst_channel, dst_native_type, dst_suffix):
     '''Generate the dispatch function to read pixels from any format'''
 
     for format in formats:
@@ -267,17 +297,20 @@ def generate_read(formats, dst_channel, dst_native_type, dst_suffix):
             generate_format_read(format, dst_channel, dst_native_type, dst_suffix)
 
     print 'void'
-    print 'lp_tile_read_%s(enum pipe_format format, %s *dst, const void *src, unsigned src_stride, unsigned x, unsigned y, unsigned w, unsigned h)' % (dst_suffix, dst_native_type)
+    print 'lp_tile_swizzle_%s(enum pipe_format format, %s *dst, const void *src, unsigned src_stride, unsigned x, unsigned y, unsigned w, unsigned h)' % (dst_suffix, dst_native_type)
     print '{'
     print '   void (*func)(%s *dst, const uint8_t *src, unsigned src_stride, unsigned x0, unsigned y0, unsigned w, unsigned h);' % dst_native_type
+    print '#ifdef DEBUG'
+    print '   lp_tile_swizzle_count += 1;'
+    print '#endif'
     print '   switch(format) {'
     for format in formats:
         if is_format_supported(format):
             print '   case %s:' % format.name
-            print '      func = &lp_tile_%s_read_%s;' % (format.short_name(), dst_suffix)
+            print '      func = &lp_tile_%s_swizzle_%s;' % (format.short_name(), dst_suffix)
             print '      break;'
     print '   default:'
-    print '      debug_printf("unsupported format\\n");'
+    print '      debug_printf("%s: unsupported format %s\\n", __FUNCTION__, util_format_name(format));'
     print '      return;'
     print '   }'
     print '   func(dst, (const uint8_t *)src, src_stride, x, y, w, h);'
@@ -285,7 +318,7 @@ def generate_read(formats, dst_channel, dst_native_type, dst_suffix):
     print
 
 
-def generate_write(formats, src_channel, src_native_type, src_suffix):
+def generate_unswizzle(formats, src_channel, src_native_type, src_suffix):
     '''Generate the dispatch function to write pixels to any format'''
 
     for format in formats:
@@ -293,18 +326,21 @@ def generate_write(formats, src_channel, src_native_type, src_suffix):
             generate_format_write(format, src_channel, src_native_type, src_suffix)
 
     print 'void'
-    print 'lp_tile_write_%s(enum pipe_format format, const %s *src, void *dst, unsigned dst_stride, unsigned x, unsigned y, unsigned w, unsigned h)' % (src_suffix, src_native_type)
+    print 'lp_tile_unswizzle_%s(enum pipe_format format, const %s *src, void *dst, unsigned dst_stride, unsigned x, unsigned y, unsigned w, unsigned h)' % (src_suffix, src_native_type)
     
     print '{'
     print '   void (*func)(const %s *src, uint8_t *dst, unsigned dst_stride, unsigned x0, unsigned y0, unsigned w, unsigned h);' % src_native_type
+    print '#ifdef DEBUG'
+    print '   lp_tile_unswizzle_count += 1;'
+    print '#endif'
     print '   switch(format) {'
     for format in formats:
         if is_format_supported(format):
             print '   case %s:' % format.name
-            print '      func = &lp_tile_%s_write_%s;' % (format.short_name(), src_suffix)
+            print '      func = &lp_tile_%s_unswizzle_%s;' % (format.short_name(), src_suffix)
             print '      break;'
     print '   default:'
-    print '      debug_printf("unsupported format\\n");'
+    print '      debug_printf("%s: unsupported format %s\\n", __FUNCTION__, util_format_name(format));'
     print '      return;'
     print '   }'
     print '   func(src, (uint8_t *)dst, dst_stride, x, y, w, h);'
@@ -325,8 +361,14 @@ def main():
     print '#include "pipe/p_compiler.h"'
     print '#include "util/u_format.h"'
     print '#include "util/u_math.h"'
+    print '#include "util/u_half.h"'
     print '#include "lp_tile_soa.h"'
     print
+    print '#ifdef DEBUG'
+    print 'unsigned lp_tile_unswizzle_count = 0;'
+    print 'unsigned lp_tile_swizzle_count = 0;'
+    print '#endif'
+    print
     print 'const unsigned char'
     print 'tile_offset[TILE_VECTOR_HEIGHT][TILE_VECTOR_WIDTH] = {'
     print '   {  0,  1,  4,  5},'
@@ -349,14 +391,12 @@ def main():
     print '};'
     print
 
-    generate_clamp()
-
     channel = Channel(UNSIGNED, True, 8)
     native_type = 'uint8_t'
     suffix = '4ub'
 
-    generate_read(formats, channel, native_type, suffix)
-    generate_write(formats, channel, native_type, suffix)
+    generate_swizzle(formats, channel, native_type, suffix)
+    generate_unswizzle(formats, channel, native_type, suffix)
 
 
 if __name__ == '__main__':