diff options
Diffstat (limited to 'src/mesa')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_gs_emit.c | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_gs_emit.c b/src/mesa/drivers/dri/i965/brw_gs_emit.c index 2c94eb0809c..9050b95c3aa 100644 --- a/src/mesa/drivers/dri/i965/brw_gs_emit.c +++ b/src/mesa/drivers/dri/i965/brw_gs_emit.c @@ -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)); } |