static void brw_gs_emit_vue(struct brw_gs_compile *c, struct brw_reg vert, GLboolean last, GLuint header) { struct brw_compile *p = &c->func; struct intel_context *intel = &c->func.brw->intel; GLboolean allocate = !last; struct brw_reg temp; if (intel->gen < 6) temp = c->reg.R0; else { temp = c->reg.temp; brw_MOV(p, retype(temp, BRW_REGISTER_TYPE_UD), retype(c->reg.R0, BRW_REGISTER_TYPE_UD)); } /* Overwrite PrimType and PrimStart in the message header, for * each vertex in turn: */ brw_MOV(p, get_element_ud(temp, 2), brw_imm_ud(header)); /* Copy the vertex from vertn into m1..mN+1: */ brw_copy8(p, brw_message_reg(1), vert, c->nr_regs); /* 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 ? temp : retype(brw_null_reg(), BRW_REGISTER_TYPE_UD), 0, temp, allocate, 1, /* used */ c->nr_regs + 1, /* msg length */ allocate ? 1 : 0, /* response length */ allocate ? 0 : 1, /* eot */ 1, /* writes_complete */ 0, /* urb offset */ BRW_URB_SWIZZLE_NONE); if (intel->gen >= 6 && allocate) brw_MOV(p, get_element_ud(c->reg.R0, 0), get_element_ud(temp, 0)); }
/** * Emit a vertex using the URB_WRITE message. Use the contents of * c->reg.header for the message header, and the registers starting at \c vert * for the vertex data. * * If \c last is true, then this is the last vertex, so no further URB space * should be allocated, and this message should end the thread. * * If \c last is false, then a new URB entry will be allocated, and its handle * will be stored in DWORD 0 of c->reg.header for use in the next URB_WRITE * message. */ static void brw_ff_gs_emit_vue(struct brw_ff_gs_compile *c, struct brw_reg vert, bool last) { struct brw_codegen *p = &c->func; int write_offset = 0; bool complete = false; 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; /* 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)); } }
/** * Emit a vertex using the URB_WRITE message. Use the contents of * c->reg.header for the message header, and the registers starting at \c vert * for the vertex data. * * If \c last is true, then this is the last vertex, so no further URB space * should be allocated, and this message should end the thread. * * If \c last is false, then a new URB entry will be allocated, and its handle * will be stored in DWORD 0 of c->reg.header for use in the next URB_WRITE * message. */ static void brw_gs_emit_vue(struct brw_gs_compile *c, struct brw_reg vert, bool last) { struct brw_compile *p = &c->func; bool allocate = !last; /* Copy the vertex from vertn into m1..mN+1: */ brw_copy8(p, brw_message_reg(1), vert, c->nr_regs); /* 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, 1, /* used */ c->nr_regs + 1, /* msg length */ allocate ? 1 : 0, /* response length */ allocate ? 0 : 1, /* eot */ 1, /* writes_complete */ 0, /* urb offset */ BRW_URB_SWIZZLE_NONE); if (allocate) { brw_MOV(p, get_element_ud(c->reg.header, 0), get_element_ud(c->reg.temp, 0)); } }