i965/gen6/gs: Implement GS_OPCODE_URB_WRITE_ALLOCATE.
authorIago Toral Quiroga <itoral@igalia.com>
Wed, 9 Jul 2014 14:28:30 +0000 (16:28 +0200)
committerIago Toral Quiroga <itoral@igalia.com>
Fri, 19 Sep 2014 13:01:15 +0000 (15:01 +0200)
Gen6 geometry shaders need to allocate URB handles for each new vertex they
emit after the first (the URB handle for the first vertex is obtained via the
FF_SYNC message).

This opcode adds the URB allocation mechanism to regular URB writes.

Acked-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
src/mesa/drivers/dri/i965/brw_defines.h
src/mesa/drivers/dri/i965/brw_shader.cpp
src/mesa/drivers/dri/i965/brw_vec4.cpp
src/mesa/drivers/dri/i965/brw_vec4.h
src/mesa/drivers/dri/i965/brw_vec4_generator.cpp

index 27a513ac58d7606d1d14a6509b0bab3be1252cef..0b5735cc02ea84bebac10a42a2661da6671b6255 100644 (file)
@@ -940,6 +940,14 @@ enum opcode {
     */
    GS_OPCODE_URB_WRITE,
 
+   /**
+    * Write geometry shader output data to the URB and request a new URB
+    * handle (gen6).
+    *
+    * This opcode doesn't do an implied move from R0 to the first MRF.
+    */
+   GS_OPCODE_URB_WRITE_ALLOCATE,
+
    /**
     * Terminate the geometry shader thread by doing an empty URB write.
     *
index 4eea74e7e10818b23ff8624a90f174e92c826404..b23524684508b627a77d40a2fd6ee7b534d3871f 100644 (file)
@@ -508,6 +508,8 @@ brw_instruction_name(enum opcode op)
 
    case GS_OPCODE_URB_WRITE:
       return "gs_urb_write";
+   case GS_OPCODE_URB_WRITE_ALLOCATE:
+      return "gs_urb_write_allocate";
    case GS_OPCODE_THREAD_END:
       return "gs_thread_end";
    case GS_OPCODE_SET_WRITE_OFFSET:
index fa992766a43c16fe91e50df19a186342c1600666..4210ee00a5481308a6d407c663dd1cc94a2d0305 100644 (file)
@@ -274,6 +274,7 @@ vec4_visitor::implied_mrf_writes(vec4_instruction *inst)
    case SHADER_OPCODE_GEN4_SCRATCH_WRITE:
       return 3;
    case GS_OPCODE_URB_WRITE:
+   case GS_OPCODE_URB_WRITE_ALLOCATE:
    case GS_OPCODE_THREAD_END:
       return 0;
    case GS_OPCODE_FF_SYNC:
index d2d2a8f5facbec53d6b4e79fe1a89dff0bfdc38b..cb863c8059567ed3e052d184d6cb0e56a44f84fb 100644 (file)
@@ -646,6 +646,7 @@ private:
 
    void generate_vs_urb_write(vec4_instruction *inst);
    void generate_gs_urb_write(vec4_instruction *inst);
+   void generate_gs_urb_write_allocate(vec4_instruction *inst);
    void generate_gs_thread_end(vec4_instruction *inst);
    void generate_gs_set_write_offset(struct brw_reg dst,
                                      struct brw_reg src0,
index c1eda12a7f3c8cbe783e3d809970ad729d7ee21f..f98c472430cad1556b05a2614c4d64687c961205 100644 (file)
@@ -466,6 +466,32 @@ vec4_generator::generate_gs_urb_write(vec4_instruction *inst)
                  BRW_URB_SWIZZLE_INTERLEAVE);
 }
 
+void
+vec4_generator::generate_gs_urb_write_allocate(vec4_instruction *inst)
+{
+   struct brw_reg src = brw_message_reg(inst->base_mrf);
+
+   /* We pass the temporary passed in src0 as the writeback register */
+   brw_urb_WRITE(p,
+                 inst->get_src(this->prog_data, 0), /* dest */
+                 inst->base_mrf, /* starting mrf reg nr */
+                 src,
+                 BRW_URB_WRITE_ALLOCATE_COMPLETE,
+                 inst->mlen,
+                 1, /* response len */
+                 inst->offset,  /* urb destination offset */
+                 BRW_URB_SWIZZLE_INTERLEAVE);
+
+   /* Now put allocated urb handle in dst.0 */
+   brw_push_insn_state(p);
+   brw_set_default_access_mode(p, BRW_ALIGN_1);
+   brw_set_default_mask_control(p, BRW_MASK_DISABLE);
+   brw_MOV(p, get_element_ud(inst->get_dst(), 0),
+           get_element_ud(inst->get_src(this->prog_data, 0), 0));
+   brw_set_default_access_mode(p, BRW_ALIGN_16);
+   brw_pop_insn_state(p);
+}
+
 void
 vec4_generator::generate_gs_thread_end(vec4_instruction *inst)
 {
@@ -1309,6 +1335,10 @@ vec4_generator::generate_code(const cfg_t *cfg)
          generate_gs_urb_write(inst);
          break;
 
+      case GS_OPCODE_URB_WRITE_ALLOCATE:
+         generate_gs_urb_write_allocate(inst);
+         break;
+
       case GS_OPCODE_THREAD_END:
          generate_gs_thread_end(inst);
          break;