i965/ff_gs: Generate URB writes using a loop.
authorPaul Berry <stereotype441@gmail.com>
Tue, 3 Sep 2013 21:38:19 +0000 (14:38 -0700)
committerPaul Berry <stereotype441@gmail.com>
Mon, 16 Sep 2013 19:53:55 +0000 (12:53 -0700)
Previously we only ever did 1 URB write, since the maximum number of
varyings we support is small enough to fit in 1 URB write (when using
BRW_URB_SWIZZLE_NONE, which is what the pre-Gen7 GS always uses).  But
we're about to increase the number of varying components we support
from 64 to 128.

With 128 varyings, the most URB writes we'll have to do is 2, but it's
just as easy to write a general-purpose loop.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/drivers/dri/i965/brw_gs_emit.c

index 2c94eb0..9050b95 100644 (file)
@@ -169,31 +169,46 @@ static void brw_ff_gs_emit_vue(struct brw_ff_gs_compile *c,
                                bool last)
 {
    struct brw_compile *p = &c->func;
-   bool allocate = !last;
+   int write_offset = 0;
+   bool complete = false;
 
-   /* Copy the vertex from vertn into m1..mN+1:
-    */
-   brw_copy8(p, brw_message_reg(1), vert, c->nr_regs);
+   do {
+      /* We can't write more than 14 registers at a time to the URB */
+      int write_len = MIN2(c->nr_regs - write_offset, 14);
+      if (write_len == c->nr_regs - write_offset)
+         complete = true;
 
-   /* Send each vertex as a seperate write to the urb.  This is
-    * different to the concept in brw_sf_emit.c, where subsequent
-    * writes are used to build up a single urb entry.  Each of these
-    * writes instantiates a seperate urb entry, and a new one must be
-    * allocated each time.
-    */
-   brw_urb_WRITE(p, 
-                allocate ? c->reg.temp
-                          : retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
-                0,
-                c->reg.header,
-                allocate ? BRW_URB_WRITE_ALLOCATE_COMPLETE
-                          : BRW_URB_WRITE_EOT_COMPLETE,
-                c->nr_regs + 1, /* msg length */
-                allocate ? 1 : 0, /* response length */
-                0,             /* urb offset */
-                BRW_URB_SWIZZLE_NONE);
-
-   if (allocate) {
+      /* Copy the vertex from vertn into m1..mN+1:
+       */
+      brw_copy8(p, brw_message_reg(1), offset(vert, write_offset), write_len);
+
+      /* Send the vertex data to the URB.  If this is the last write for this
+       * vertex, then we mark it as complete, and either end the thread or
+       * allocate another vertex URB entry (depending whether this is the last
+       * vertex).
+       */
+      enum brw_urb_write_flags flags;
+      if (!complete)
+         flags = BRW_URB_WRITE_NO_FLAGS;
+      else if (last)
+         flags = BRW_URB_WRITE_EOT_COMPLETE;
+      else
+         flags = BRW_URB_WRITE_ALLOCATE_COMPLETE;
+      brw_urb_WRITE(p,
+                    (flags & BRW_URB_WRITE_ALLOCATE) ? c->reg.temp
+                    : retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
+                    0,
+                    c->reg.header,
+                    flags,
+                    write_len + 1, /* msg length */
+                    (flags & BRW_URB_WRITE_ALLOCATE) ? 1
+                    : 0, /* response length */
+                    write_offset,  /* urb offset */
+                    BRW_URB_SWIZZLE_NONE);
+      write_offset += write_len;
+   } while (!complete);
+
+   if (!last) {
       brw_MOV(p, get_element_ud(c->reg.header, 0),
               get_element_ud(c->reg.temp, 0));
    }