gallium: decompose quad strips into quads if supported
authorantonino <antonino.maniscalco@collabora.com>
Mon, 6 Feb 2023 14:44:01 +0000 (15:44 +0100)
committerMarge Bot <emma+marge@anholt.net>
Fri, 24 Mar 2023 13:11:12 +0000 (13:11 +0000)
This changes gallium to decompose quad strips into quads instead of triangles
when the driver advertises support for them.

This should result in a more correct result when those are drawn
with the line raster primitve (avoids showing the diagonal line).

Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21987>

src/gallium/auxiliary/indices/u_indices.c
src/gallium/auxiliary/indices/u_indices_gen.py

index 53dbb76..e430723 100644 (file)
@@ -57,6 +57,10 @@ u_index_prim_type_convert(unsigned hw_mask, enum pipe_prim_type prim, bool pv_ma
    case PIPE_PRIM_TRIANGLE_FAN:
    case PIPE_PRIM_QUADS:
    case PIPE_PRIM_QUAD_STRIP:
+      if ((hw_mask & (1<<PIPE_PRIM_QUADS)) && pv_matches)
+         return PIPE_PRIM_QUADS;
+      else
+         return PIPE_PRIM_TRIANGLES;
    case PIPE_PRIM_POLYGON:
       return PIPE_PRIM_TRIANGLES;
    case PIPE_PRIM_LINES_ADJACENCY:
@@ -140,8 +144,9 @@ u_index_translator(unsigned hw_mask,
 
       return U_TRANSLATE_MEMCPY;
    }
-   *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim];
    *out_prim = u_index_prim_type_convert(hw_mask, prim, in_pv == out_pv);
+   *out_translate = (*out_prim == PIPE_PRIM_QUADS ? translate_quads : translate)
+      [in_idx][out_idx][in_pv][out_pv][prim_restart][prim];
    *out_nr = u_index_count_converted_indices(hw_mask, in_pv == out_pv, prim, nr);
 
    return ret;
@@ -170,9 +175,9 @@ u_index_count_converted_indices(unsigned hw_mask, bool pv_matches, enum pipe_pri
    case PIPE_PRIM_TRIANGLE_FAN:
       return (nr - 2) * 3;
    case PIPE_PRIM_QUADS:
-      return (nr / 4) * 6;
+      return ((hw_mask & (1<<PIPE_PRIM_QUADS)) && pv_matches) ? nr : (nr / 4) * 6;
    case PIPE_PRIM_QUAD_STRIP:
-      return (nr - 2) * 3;
+      return ((hw_mask & (1<<PIPE_PRIM_QUADS)) && pv_matches) ? (nr - 2) * 2 : (nr - 2) * 3;
    case PIPE_PRIM_POLYGON:
       return (nr - 2) * 3;
    case PIPE_PRIM_LINES_ADJACENCY:
@@ -237,9 +242,11 @@ u_index_generator(unsigned hw_mask,
    if ((hw_mask & (1<<prim)) &&
        (in_pv == out_pv)) {
 
-      *out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS];
+      *out_generate = (*out_prim == PIPE_PRIM_QUADS ? generate_quads : generate)
+         [out_idx][in_pv][out_pv][PIPE_PRIM_POINTS];
       return U_GENERATE_LINEAR;
    }
-   *out_generate = generate[out_idx][in_pv][out_pv][prim];
+   *out_generate = (*out_prim == PIPE_PRIM_QUADS ? generate_quads : generate)
+      [out_idx][in_pv][out_pv][prim];
    return prim == PIPE_PRIM_LINE_LOOP ? U_GENERATE_ONE_OFF : U_GENERATE_REUSABLE;
 }
index de3bf95..0364069 100644 (file)
@@ -51,6 +51,8 @@ PRIMS=('points',
        'trisadj',
        'tristripadj')
 
+OUT_TRIS, OUT_QUADS = 'tris', 'quads'
+
 LONGPRIMS=('PIPE_PRIM_POINTS',
            'PIPE_PRIM_LINES',
            'PIPE_PRIM_LINE_STRIP',
@@ -91,6 +93,9 @@ def prolog(f: 'T.TextIO') -> None:
 static u_translate_func translate[IN_COUNT][OUT_COUNT][PV_COUNT][PV_COUNT][PR_COUNT][PRIM_COUNT];
 static u_generate_func  generate[OUT_COUNT][PV_COUNT][PV_COUNT][PRIM_COUNT];
 
+static u_translate_func translate_quads[IN_COUNT][OUT_COUNT][PV_COUNT][PV_COUNT][PR_COUNT][PRIM_COUNT];
+static u_generate_func  generate_quads[OUT_COUNT][PV_COUNT][PV_COUNT][PRIM_COUNT];
+
 
 ''')
 
@@ -121,13 +126,21 @@ def do_tri(f: 'T.TextIO', intype, outtype, ptr, v0, v1, v2, inpv, outpv ):
     else:
         shape(f, intype, outtype, ptr, v2, v0, v1 )
 
-def do_quad(f: 'T.TextIO', intype, outtype, ptr, v0, v1, v2, v3, inpv, outpv ):
-    if inpv == LAST:
-        do_tri(f, intype, outtype, ptr+'+0',  v0, v1, v3, inpv, outpv );
-        do_tri(f, intype, outtype, ptr+'+3',  v1, v2, v3, inpv, outpv );
+def do_quad(f: 'T.TextIO', intype, outtype, ptr, v0, v1, v2, v3, inpv, outpv, out_prim ):
+    if out_prim == OUT_TRIS:
+        if inpv == LAST:
+            do_tri(f, intype, outtype, ptr+'+0',  v0, v1, v3, inpv, outpv );
+            do_tri(f, intype, outtype, ptr+'+3',  v1, v2, v3, inpv, outpv );
+        else:
+            do_tri(f, intype, outtype, ptr+'+0',  v0, v1, v2, inpv, outpv );
+            do_tri(f, intype, outtype, ptr+'+3',  v0, v2, v3, inpv, outpv );
     else:
-        do_tri(f, intype, outtype, ptr+'+0',  v0, v1, v2, inpv, outpv );
-        do_tri(f, intype, outtype, ptr+'+3',  v0, v2, v3, inpv, outpv );
+        if inpv == outpv:
+            shape(f, intype, outtype, ptr, v0, v1, v2, v3)
+        elif inpv == FIRST:
+            shape(f, intype, outtype, ptr, v1, v2, v3, v0)
+        else:
+            shape(f, intype, outtype, ptr, v3, v0, v1, v2)
 
 def do_lineadj(f: 'T.TextIO', intype, outtype, ptr, v0, v1, v2, v3, inpv, outpv ):
     if inpv == outpv:
@@ -141,14 +154,14 @@ def do_triadj(f: 'T.TextIO', intype, outtype, ptr, v0, v1, v2, v3, v4, v5, inpv,
     else:
         shape(f, intype, outtype, ptr, v4, v5, v0, v1, v2, v3 )
 
-def name(intype, outtype, inpv, outpv, pr, prim):
+def name(intype, outtype, inpv, outpv, pr, prim, out_prim):
     if intype == GENERATE:
-        return 'generate_' + prim + '_' + outtype + '_' + inpv + '2' + outpv
+        return 'generate_' + prim + '_' + outtype + '_' + inpv + '2' + outpv + '_' + str(out_prim)
     else:
-        return 'translate_' + prim + '_' + intype + '2' + outtype + '_' + inpv + '2' + outpv + '_' + pr
+        return 'translate_' + prim + '_' + intype + '2' + outtype + '_' + inpv + '2' + outpv + '_' + pr + '_' + str(out_prim)
 
-def preamble(f: 'T.TextIO', intype, outtype, inpv, outpv, pr, prim):
-    f.write('static void ' + name( intype, outtype, inpv, outpv, pr, prim ) + '(\n')
+def preamble(f: 'T.TextIO', intype, outtype, inpv, outpv, pr, prim, out_prim):
+    f.write('static void ' + name( intype, outtype, inpv, outpv, pr, prim, out_prim ) + '(\n')
     if intype != GENERATE:
         f.write('    const void * restrict _in,\n')
     f.write('    unsigned start,\n')
@@ -186,28 +199,28 @@ def prim_restart(f: 'T.TextIO', in_verts, out_verts, out_prims, close_func = Non
         f.write('      }\n')
 
 def points(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
-    preamble(f, intype, outtype, inpv, outpv, pr, prim='points')
+    preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='points')
     f.write('  for (i = start, j = 0; j < out_nr; j++, i++) {\n')
     do_point(f, intype, outtype, 'out+j',  'i' );
     f.write('   }\n')
     postamble(f)
 
 def lines(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
-    preamble(f, intype, outtype, inpv, outpv, pr, prim='lines')
+    preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='lines')
     f.write('  for (i = start, j = 0; j < out_nr; j+=2, i+=2) {\n')
     do_line(f,  intype, outtype, 'out+j',  'i', 'i+1', inpv, outpv );
     f.write('   }\n')
     postamble(f)
 
 def linestrip(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
-    preamble(f, intype, outtype, inpv, outpv, pr, prim='linestrip')
+    preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='linestrip')
     f.write('  for (i = start, j = 0; j < out_nr; j+=2, i++) {\n')
     do_line(f, intype, outtype, 'out+j',  'i', 'i+1', inpv, outpv );
     f.write('   }\n')
     postamble(f)
 
 def lineloop(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
-    preamble(f, intype, outtype, inpv, outpv, pr, prim='lineloop')
+    preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='lineloop')
     f.write('  unsigned end = start;\n')
     f.write('  for (i = start, j = 0; j < out_nr - 2; j+=2, i++) {\n')
     if pr == PRENABLE:
@@ -226,7 +239,7 @@ def lineloop(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
     postamble(f)
 
 def tris(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
-    preamble(f, intype, outtype, inpv, outpv, pr, prim='tris')
+    preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='tris')
     f.write('  for (i = start, j = 0; j < out_nr; j+=3, i+=3) {\n')
     do_tri(f, intype, outtype, 'out+j',  'i', 'i+1', 'i+2', inpv, outpv );
     f.write('   }\n')
@@ -234,7 +247,7 @@ def tris(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
 
 
 def tristrip(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
-    preamble(f, intype, outtype, inpv, outpv, pr, prim='tristrip')
+    preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='tristrip')
     f.write('  for (i = start, j = 0; j < out_nr; j+=3, i++) {\n')
     if inpv == FIRST:
         do_tri(f, intype, outtype, 'out+j',  'i', 'i+1+(i&1)', 'i+2-(i&1)', inpv, outpv );
@@ -245,7 +258,7 @@ def tristrip(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
 
 
 def trifan(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
-    preamble(f, intype, outtype, inpv, outpv, pr, prim='trifan')
+    preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='trifan')
     f.write('  for (i = start, j = 0; j < out_nr; j+=3, i++) {\n')
 
     if pr == PRENABLE:
@@ -264,7 +277,7 @@ def trifan(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
 
 
 def polygon(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
-    preamble(f, intype, outtype, inpv, outpv, pr, prim='polygon')
+    preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='polygon')
     f.write('  for (i = start, j = 0; j < out_nr; j+=3, i++) {\n')
     if pr == PRENABLE:
         def close_func(index):
@@ -279,33 +292,43 @@ def polygon(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
     postamble(f)
 
 
-def quads(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
-    preamble(f, intype, outtype, inpv, outpv, pr, prim='quads')
-    f.write('  for (i = start, j = 0; j < out_nr; j+=6, i+=4) {\n')
-    if pr == PRENABLE:
+def quads(f: 'T.TextIO', intype, outtype, inpv, outpv, pr, out_prim):
+    preamble(f, intype, outtype, inpv, outpv, pr, out_prim=out_prim, prim='quads')
+    if out_prim == OUT_TRIS:
+        f.write('  for (i = start, j = 0; j < out_nr; j+=6, i+=4) {\n')
+    else:
+        f.write('  for (i = start, j = 0; j < out_nr; j+=4, i+=4) {\n')
+    if pr == PRENABLE and out_prim == OUT_TRIS:
         prim_restart(f, 4, 3, 2)
+    elif pr == PRENABLE:
+        prim_restart(f, 4, 4, 1)
 
-    do_quad(f, intype, outtype, 'out+j', 'i+0', 'i+1', 'i+2', 'i+3', inpv, outpv );
+    do_quad(f, intype, outtype, 'out+j', 'i+0', 'i+1', 'i+2', 'i+3', inpv, outpv, out_prim );
     f.write('   }\n')
     postamble(f)
 
 
-def quadstrip(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
-    preamble(f, intype, outtype, inpv, outpv, pr, prim='quadstrip')
-    f.write('  for (i = start, j = 0; j < out_nr; j+=6, i+=2) {\n')
-    if pr == PRENABLE:
+def quadstrip(f: 'T.TextIO', intype, outtype, inpv, outpv, pr, out_prim):
+    preamble(f, intype, outtype, inpv, outpv, pr, out_prim=out_prim, prim='quadstrip')
+    if out_prim == OUT_TRIS:
+        f.write('  for (i = start, j = 0; j < out_nr; j+=6, i+=2) {\n')
+    else:
+        f.write('  for (i = start, j = 0; j < out_nr; j+=4, i+=2) {\n')
+    if pr == PRENABLE and out_prim == OUT_TRIS:
         prim_restart(f, 4, 3, 2)
+    elif pr == PRENABLE:
+        prim_restart(f, 4, 4, 1)
 
     if inpv == LAST:
-        do_quad(f, intype, outtype, 'out+j', 'i+2', 'i+0', 'i+1', 'i+3', inpv, outpv );
+        do_quad(f, intype, outtype, 'out+j', 'i+2', 'i+0', 'i+1', 'i+3', inpv, outpv, out_prim );
     else:
-        do_quad(f, intype, outtype, 'out+j', 'i+0', 'i+1', 'i+3', 'i+2', inpv, outpv );
+        do_quad(f, intype, outtype, 'out+j', 'i+0', 'i+1', 'i+3', 'i+2', inpv, outpv, out_prim );
     f.write('   }\n')
     postamble(f)
 
 
 def linesadj(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
-    preamble(f, intype, outtype, inpv, outpv, pr, prim='linesadj')
+    preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='linesadj')
     f.write('  for (i = start, j = 0; j < out_nr; j+=4, i+=4) {\n')
     do_lineadj(f, intype, outtype, 'out+j',  'i+0', 'i+1', 'i+2', 'i+3', inpv, outpv )
     f.write('  }\n')
@@ -313,7 +336,7 @@ def linesadj(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
 
 
 def linestripadj(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
-    preamble(f, intype, outtype, inpv, outpv, pr, prim='linestripadj')
+    preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='linestripadj')
     f.write('  for (i = start, j = 0; j < out_nr; j+=4, i++) {\n')
     do_lineadj(f, intype, outtype, 'out+j',  'i+0', 'i+1', 'i+2', 'i+3', inpv, outpv )
     f.write('  }\n')
@@ -321,7 +344,7 @@ def linestripadj(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
 
 
 def trisadj(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
-    preamble(f, intype, outtype, inpv, outpv, pr, prim='trisadj')
+    preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='trisadj')
     f.write('  for (i = start, j = 0; j < out_nr; j+=6, i+=6) {\n')
     do_triadj(f, intype, outtype, 'out+j',  'i+0', 'i+1', 'i+2', 'i+3',
               'i+4', 'i+5', inpv, outpv )
@@ -330,7 +353,7 @@ def trisadj(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
 
 
 def tristripadj(f: 'T.TextIO', intype, outtype, inpv, outpv, pr):
-    preamble(f, intype, outtype, inpv, outpv, pr, prim='tristripadj')
+    preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='tristripadj')
     f.write('  for (i = start, j = 0; j < out_nr; i+=2, j+=6) {\n')
     f.write('    if (i % 4 == 0) {\n')
     f.write('      /* even triangle */\n')
@@ -357,31 +380,44 @@ def emit_funcs(f: 'T.TextIO') -> None:
         tris(f, intype, outtype, inpv, outpv, pr)
         tristrip(f, intype, outtype, inpv, outpv, pr)
         trifan(f, intype, outtype, inpv, outpv, pr)
-        quads(f, intype, outtype, inpv, outpv, pr)
-        quadstrip(f, intype, outtype, inpv, outpv, pr)
+        quads(f, intype, outtype, inpv, outpv, pr, OUT_TRIS)
+        quadstrip(f, intype, outtype, inpv, outpv, pr, OUT_TRIS)
         polygon(f, intype, outtype, inpv, outpv, pr)
         linesadj(f, intype, outtype, inpv, outpv, pr)
         linestripadj(f, intype, outtype, inpv, outpv, pr)
         trisadj(f, intype, outtype, inpv, outpv, pr)
         tristripadj(f, intype, outtype, inpv, outpv, pr)
 
-def init(f: 'T.TextIO', intype, outtype, inpv, outpv, pr, prim):
+    for intype, outtype, inpv, outpv, pr in itertools.product(
+            INTYPES, OUTTYPES, [FIRST, LAST], [FIRST, LAST], [PRDISABLE, PRENABLE]):
+        if pr == PRENABLE and intype == GENERATE:
+            continue
+        quads(f, intype, outtype, inpv, outpv, pr, OUT_QUADS)
+        quadstrip(f, intype, outtype, inpv, outpv, pr, OUT_QUADS)
+
+def init(f: 'T.TextIO', intype, outtype, inpv, outpv, pr, prim, out_prim=OUT_TRIS):
+    generate_name = 'generate'
+    translate_name = 'translate'
+    if out_prim == OUT_QUADS:
+        generate_name = 'generate_quads'
+        translate_name = 'translate_quads'
+
     if intype == GENERATE:
-        f.write('generate[' +
+        f.write(f'{generate_name}[' +
                 outtype_idx[outtype] +
                 '][' + pv_idx[inpv] +
                 '][' + pv_idx[outpv] +
                 '][' + longprim[prim] +
-                '] = ' + name( intype, outtype, inpv, outpv, pr, prim ) + ';\n')
+                '] = ' + name( intype, outtype, inpv, outpv, pr, prim, out_prim ) + ';\n')
     else:
-        f.write('translate[' +
+        f.write(f'{translate_name}[' +
                 intype_idx[intype] +
                 '][' + outtype_idx[outtype] +
                 '][' + pv_idx[inpv] +
                 '][' + pv_idx[outpv] +
                 '][' + pr_idx[pr] +
                 '][' + longprim[prim] +
-                '] = ' + name( intype, outtype, inpv, outpv, pr, prim ) + ';\n')
+                '] = ' + name( intype, outtype, inpv, outpv, pr, prim, out_prim ) + ';\n')
 
 
 def emit_all_inits(f: 'T.TextIO'):
@@ -389,6 +425,10 @@ def emit_all_inits(f: 'T.TextIO'):
             INTYPES, OUTTYPES, PVS, PVS, PRS, PRIMS):
         init(f,intype, outtype, inpv, outpv, pr, prim)
 
+    for intype, outtype, inpv, outpv, pr, prim in itertools.product(
+            INTYPES, OUTTYPES, PVS, PVS, PRS, ['quads', 'quadstrip']):
+        init(f,intype, outtype, inpv, outpv, pr, prim, OUT_QUADS)
+
 def emit_init(f: 'T.TextIO'):
     f.write('void u_index_init( void )\n')
     f.write('{\n')