gallium: move clear paths from rgba to a pointer to a color union (v2)
[mesa.git] / src / gallium / drivers / i965 / brw_vs_emit.c
index 26f0ec5a11a731bea153c65a91818fc880d30f39..559f0c61d8dd0a9e3a95d90872ea7f40550c697b 100644 (file)
 #include "brw_context.h"
 #include "brw_vs.h"
 #include "brw_debug.h"
+#include "brw_disasm.h"
 
+/* Choose one of the 4 vec4's which can be packed into each 16-wide reg.
+ */
+static INLINE struct brw_reg brw_vec4_grf_repeat( GLuint reg, GLuint slot )
+{
+   int nr = reg + slot/2;
+   int subnr = (slot%2) * 4;
+
+   return stride(brw_vec4_grf(nr, subnr), 0, 4, 1);
+}
 
 
 static struct brw_reg get_tmp( struct brw_vs_compile *c )
@@ -66,6 +76,38 @@ static void release_tmps( struct brw_vs_compile *c )
 }
 
 
+static boolean is_position_output( struct brw_vs_compile *c,
+                                   unsigned vs_output )
+{
+   const struct brw_vertex_shader *vs = c->vp;
+   unsigned semantic = vs->info.output_semantic_name[vs_output];
+   unsigned index = vs->info.output_semantic_index[vs_output];
+      
+   return (semantic == TGSI_SEMANTIC_POSITION &&
+           index == 0);
+}
+
+
+static boolean find_output_slot( struct brw_vs_compile *c,
+                                  unsigned vs_output,
+                                  unsigned *fs_input_slot )
+{
+   const struct brw_vertex_shader *vs = c->vp;
+   unsigned semantic = vs->info.output_semantic_name[vs_output];
+   unsigned index = vs->info.output_semantic_index[vs_output];
+   unsigned i;
+
+   for (i = 0; i < c->key.fs_signature.nr_inputs; i++) {
+      if (c->key.fs_signature.input[i].semantic == semantic &&
+          c->key.fs_signature.input[i].semantic_index == index) {
+         *fs_input_slot = i;
+         return TRUE;
+      }
+   }
+
+   return FALSE;
+}
+
 
 /**
  * Preallocate GRF register before code emit.
@@ -74,7 +116,8 @@ static void release_tmps( struct brw_vs_compile *c )
  */
 static void brw_vs_alloc_regs( struct brw_vs_compile *c )
 {
-   GLuint i, reg = 0, mrf;
+   struct brw_context *brw = c->func.brw;
+   GLuint i, reg = 0, subreg = 0, mrf;
    int attributes_in_vue;
 
    /* Determine whether to use a real constant buffer or use a block
@@ -105,33 +148,57 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c )
    /* User clip planes from curbe: 
     */
    if (c->key.nr_userclip) {
-      for (i = 0; i < c->key.nr_userclip; i++) {
-        c->userplane[i] = stride( brw_vec4_grf(reg+3+i/2, (i%2) * 4), 0, 4, 1);
+      /* Skip over fixed planes:  Or never read them into vs unit?
+       */
+      subreg += 6;
+
+      for (i = 0; i < c->key.nr_userclip; i++, subreg++) {
+        c->userplane[i] = 
+            stride( brw_vec4_grf(reg+subreg/2, (subreg%2) * 4), 0, 4, 1);
       }     
 
       /* Deal with curbe alignment:
        */
-      reg += ((6 + c->key.nr_userclip + 3) / 4) * 2;
+      subreg = align(subreg, 2);
+      /*reg += ((6 + c->key.nr_userclip + 3) / 4) * 2;*/
    }
 
-   /* Vertex program parameters from curbe:
+
+   /* Immediates: always in the curbe.
+    *
+    * XXX: Can try to encode some immediates as brw immediates
+    * XXX: Make sure ureg sets minimal immediate size and respect it
+    * here.
     */
-   if (c->vp->use_const_buffer) {
-      /* get constants from a real constant buffer */
-      c->prog_data.curb_read_length = 0;
-      c->prog_data.nr_params = 4; /* XXX 0 causes a bug elsewhere... */
+   for (i = 0; i < c->vp->info.immediate_count; i++, subreg++) {
+      c->regs[TGSI_FILE_IMMEDIATE][i] = 
+         stride( brw_vec4_grf(reg+subreg/2, (subreg%2) * 4), 0, 4, 1);
    }
-   else {
-      /* use a section of the GRF for constants */
+   c->prog_data.nr_params = c->vp->info.immediate_count * 4;
+
+
+   /* Vertex constant buffer.
+    *
+    * Constants from the buffer can be either cached in the curbe or
+    * loaded as needed from the actual constant buffer.
+    */
+   if (!c->vp->use_const_buffer) {
       GLuint nr_params = c->vp->info.file_max[TGSI_FILE_CONSTANT] + 1;
-      for (i = 0; i < nr_params; i++) {
-         c->regs[TGSI_FILE_CONSTANT][i] = stride( brw_vec4_grf(reg+i/2, (i%2) * 4), 0, 4, 1);
+
+      for (i = 0; i < nr_params; i++, subreg++) {
+         c->regs[TGSI_FILE_CONSTANT][i] =
+            stride( brw_vec4_grf(reg+subreg/2, (subreg%2) * 4), 0, 4, 1);
       }
-      reg += (nr_params + 1) / 2;
-      c->prog_data.curb_read_length = reg - 1;
-      c->prog_data.nr_params = nr_params * 4;
+
+      c->prog_data.nr_params += nr_params * 4;
    }
 
+   /* All regs allocated
+    */
+   reg += (subreg + 1) / 2;
+   c->prog_data.curb_read_length = reg - 1;
+
+
    /* Allocate input regs:  
     */
    c->nr_inputs = c->vp->info.num_inputs;
@@ -146,68 +213,55 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c )
    if (c->nr_inputs == 0)
       reg++;
 
-   /* Allocate a GRF and load immediate values by hand with 4 MOVs!!!
-    *
-    * XXX: Try to encode float immediates as brw immediates
-    * XXX: Put immediates into the CURBE.
-    * XXX: Make sure ureg sets minimal immediate size and respect it
-    * here.
-    */
-   for (i = 0; i < c->nr_immediates; i++) {
-      struct brw_reg r;
-      int j;
-
-      r = brw_vec8_grf(reg, 0);
-
-      for (j = 0; j < 4; j++) {
-        brw_MOV(&c->func, 
-                brw_writemask(r, (1<<j)), 
-                brw_imm_f(c->immediate[i][j]));
-      }
-
-      reg++;
-   }
 
 
    /* Allocate outputs.  The non-position outputs go straight into message regs.
     */
    c->nr_outputs = c->prog_data.nr_outputs;
-   c->first_output = reg;
-   c->first_overflow_output = 0;
 
-   if (c->chipset.is_igdng)
+   if (brw->gen == 5)
       mrf = 8;
    else
       mrf = 4;
 
+   
+   if (c->key.fs_signature.nr_inputs > BRW_MAX_MRF) {
+      c->overflow_grf_start = reg;
+      c->overflow_count = c->key.fs_signature.nr_inputs - BRW_MAX_MRF;
+      reg += c->overflow_count;
+   }
+
    /* XXX: need to access vertex output semantics here:
     */
-   for (i = 0; i < c->prog_data.nr_outputs; i++) {
-      assert(i < Elements(c->regs[TGSI_FILE_OUTPUT]));
+   for (i = 0; i < c->nr_outputs; i++) {
+      unsigned slot;
 
-      /* XXX: Hardwire position to zero:
+      /* XXX: Put output position in slot zero always.  Clipper, etc,
+       * need access to this reg.
        */
-      if (i == 0) {
-        c->regs[TGSI_FILE_OUTPUT][i] = brw_vec8_grf(reg, 0);
+      if (is_position_output(c, i)) {
+        c->regs[TGSI_FILE_OUTPUT][i] = brw_vec8_grf(reg, 0); /* copy to mrf 0 */
         reg++;
       }
-      /* XXX: disable psiz:
-       */
-      else if (0) {
-        c->regs[TGSI_FILE_OUTPUT][i] = brw_vec8_grf(reg, 0);
-        reg++;
-        mrf++;         /* just a placeholder?  XXX fix later stages & remove this */
-      }
-      else if (mrf < 16) {
-        c->regs[TGSI_FILE_OUTPUT][i] = brw_message_reg(mrf);
-        mrf++;
+      else if (find_output_slot(c, i, &slot)) {
+         
+         if (0 /* is_psize_output(c, i) */ ) {
+            /* c->psize_out.grf = reg; */
+            /* c->psize_out.mrf = i; */
+         }
+         
+         /* The first (16-4) outputs can go straight into the message regs.
+          */
+         if (slot + mrf < BRW_MAX_MRF) {
+            c->regs[TGSI_FILE_OUTPUT][i] = brw_message_reg(slot + mrf);
+         }
+         else {
+            int grf = c->overflow_grf_start + slot - BRW_MAX_MRF;
+            c->regs[TGSI_FILE_OUTPUT][i] = brw_vec8_grf(grf, 0);
+         }
       }
       else {
-        /* too many vertex results to fit in MRF, use GRF for overflow */
-        if (!c->first_overflow_output)
-           c->first_overflow_output = i;
-        c->regs[TGSI_FILE_OUTPUT][i] = brw_vec8_grf(reg, 0);
-        reg++;
+         c->regs[TGSI_FILE_OUTPUT][i] = brw_null_reg();
       }
    }     
 
@@ -280,7 +334,7 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c )
     */
    attributes_in_vue = MAX2(c->nr_outputs, c->nr_inputs);
 
-   if (c->chipset.is_igdng)
+   if (brw->gen == 5)
       c->prog_data.urb_entry_size = (attributes_in_vue + 6 + 3) / 4;
    else
       c->prog_data.urb_entry_size = (attributes_in_vue + 2 + 3) / 4;
@@ -855,6 +909,7 @@ get_constant(struct brw_vs_compile *c,
 }
 
 
+#if 0
 
 /* TODO: relative addressing!
  */
@@ -883,6 +938,8 @@ static struct brw_reg get_reg( struct brw_vs_compile *c,
    }
 }
 
+#endif
+
 
 /**
  * Indirect addressing:  get reg[[arg] + offset].
@@ -1001,22 +1058,22 @@ static struct brw_reg get_arg( struct brw_vs_compile *c,
 {
    struct brw_reg reg;
 
-   if (src->SrcRegister.File == TGSI_FILE_NULL)
+   if (src->Register.File == TGSI_FILE_NULL)
       return brw_null_reg();
 
    reg = get_src_reg(c, argIndex,
-                    src->SrcRegister.File,
-                    src->SrcRegister.Index,
-                    src->SrcRegister.Indirect);
+                    src->Register.File,
+                    src->Register.Index,
+                    src->Register.Indirect);
 
    /* Convert 3-bit swizzle to 2-bit.  
     */
-   reg.dw1.bits.swizzle = BRW_SWIZZLE4(src->SrcRegister.SwizzleX,
-                                      src->SrcRegister.SwizzleY,
-                                      src->SrcRegister.SwizzleZ,
-                                      src->SrcRegister.SwizzleW);
+   reg.dw1.bits.swizzle = BRW_SWIZZLE4(src->Register.SwizzleX,
+                                      src->Register.SwizzleY,
+                                      src->Register.SwizzleZ,
+                                      src->Register.SwizzleW);
 
-   reg.negate = src->SrcRegister.Negate ? 1 : 0;   
+   reg.negate = src->Register.Negate ? 1 : 0;   
 
    /* XXX: abs, absneg
     */
@@ -1068,19 +1125,14 @@ static struct brw_reg get_dst( struct brw_vs_compile *c,
 static void emit_vertex_write( struct brw_vs_compile *c)
 {
    struct brw_compile *p = &c->func;
+   struct brw_context *brw = p->brw;
    struct brw_reg m0 = brw_message_reg(0);
    struct brw_reg pos = c->regs[TGSI_FILE_OUTPUT][VERT_RESULT_HPOS];
    struct brw_reg ndc;
    int eot;
+   int i;
    GLuint len_vertext_header = 2;
 
-   if (c->key.copy_edgeflag) {
-      assert(0);
-      brw_MOV(p, 
-             get_reg(c, TGSI_FILE_OUTPUT, 0),
-             get_reg(c, TGSI_FILE_INPUT, 0));
-   }
-
    /* Build ndc coords */
    ndc = get_tmp(c);
    /* ndc = 1.0 / pos.w */
@@ -1093,7 +1145,7 @@ static void emit_vertex_write( struct brw_vs_compile *c)
     */
    if (c->prog_data.writes_psiz ||
        c->key.nr_userclip || 
-       c->chipset.is_965)
+       brw->has_negative_rhw_bug)
    {
       struct brw_reg header1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
       GLuint i;
@@ -1124,7 +1176,7 @@ static void emit_vertex_write( struct brw_vs_compile *c)
        * Later, clipping will detect ucp[6] and ensure the primitive is
        * clipped against all fixed planes.
        */
-      if (c->chipset.is_965) {
+      if (brw->has_negative_rhw_bug) {
         brw_CMP(p,
                 vec8(brw_null_reg()),
                 BRW_CONDITIONAL_L,
@@ -1152,7 +1204,7 @@ static void emit_vertex_write( struct brw_vs_compile *c)
    brw_set_access_mode(p, BRW_ALIGN_1);
    brw_MOV(p, offset(m0, 2), ndc);
 
-   if (c->chipset.is_igdng) {
+   if (brw->gen == 5) {
        /* There are 20 DWs (D0-D19) in VUE vertex header on IGDNG */
        brw_MOV(p, offset(m0, 3), pos); /* a portion of vertex header */
        /* m4, m5 contain the distances from vertex to the user clip planeXXX. 
@@ -1167,7 +1219,7 @@ static void emit_vertex_write( struct brw_vs_compile *c)
        len_vertext_header = 2;
    }
 
-   eot = (c->first_overflow_output == 0);
+   eot = (c->overflow_count == 0);
 
    brw_urb_WRITE(p, 
                 brw_null_reg(), /* dest */
@@ -1182,19 +1234,22 @@ static void emit_vertex_write( struct brw_vs_compile *c)
                 0,             /* urb destination offset */
                 BRW_URB_SWIZZLE_INTERLEAVE);
 
-   if (c->first_overflow_output > 0) {
-      /* Not all of the vertex outputs/results fit into the MRF.
-       * Move the overflowed attributes from the GRF to the MRF and
-       * issue another brw_urb_WRITE().
-       */
+   /* Not all of the vertex outputs/results fit into the MRF.
+    * Move the overflowed attributes from the GRF to the MRF and
+    * issue another brw_urb_WRITE().
+    */
+   for (i = 0; i < c->overflow_count; i += BRW_MAX_MRF) {
+      unsigned nr = MIN2(c->overflow_count - i, BRW_MAX_MRF);
+      GLuint j;
+
+      eot = (i + nr >= c->overflow_count);
+
       /* XXX I'm not 100% sure about which MRF regs to use here.  Starting
        * at mrf[4] atm...
        */
-      GLuint i, mrf = 0;
-      for (i = c->first_overflow_output; i < c->prog_data.nr_outputs; i++) {
-        /* move from GRF to MRF */
-        brw_MOV(p, brw_message_reg(4+mrf), c->regs[TGSI_FILE_OUTPUT][i]);
-        mrf++;
+      for (j = 0; j < nr; j++) {
+        brw_MOV(p, brw_message_reg(4+j), 
+                 brw_vec8_grf(c->overflow_grf_start + i + j, 0));
       }
 
       brw_urb_WRITE(p,
@@ -1203,11 +1258,11 @@ static void emit_vertex_write( struct brw_vs_compile *c)
                     c->r0,          /* src */
                     0,              /* allocate */
                     1,              /* used */
-                    mrf+1,          /* msg len */
+                    nr+1,          /* msg len */
                     0,              /* response len */
-                    1,              /* eot */
-                    1,              /* writes complete */
-                    BRW_MAX_MRF-1,  /* urb destination offset */
+                    eot,            /* eot */
+                    eot,            /* writes complete */
+                    i-1,            /* urb destination offset */
                     BRW_URB_SWIZZLE_INTERLEAVE);
    }
 }
@@ -1284,8 +1339,9 @@ static void emit_insn(struct brw_vs_compile *c,
                      const struct tgsi_full_instruction *inst)
 {
    unsigned opcode = inst->Instruction.Opcode;
-   unsigned label = inst->InstructionExtLabel.Label;
+   unsigned label = inst->Label.Label;
    struct brw_compile *p = &c->func;
+   struct brw_context *brw = p->brw;
    struct brw_reg args[3], dst;
    GLuint i;
 
@@ -1297,7 +1353,7 @@ static void emit_insn(struct brw_vs_compile *c,
    /* Get argument regs.
     */
    for (i = 0; i < 3; i++) {
-      args[i] = get_arg(c, &inst->FullSrcRegisters[i], i);
+      args[i] = get_arg(c, &inst->Src[i], i);
    }
 
    /* Get dest regs.  Note that it is possible for a reg to be both
@@ -1305,9 +1361,9 @@ static void emit_insn(struct brw_vs_compile *c,
     * care needs to be taken emitting multi-operation instructions.
     */ 
    dst = get_dst(c, 
-                inst->FullDstRegisters[0].DstRegister.File,
-                inst->FullDstRegisters[0].DstRegister.Index,
-                inst->FullDstRegisters[0].DstRegister.WriteMask);
+                inst->Dst[0].Register.File,
+                inst->Dst[0].Register.Index,
+                inst->Dst[0].Register.WriteMask);
 
    /* XXX: saturate
     */
@@ -1393,7 +1449,8 @@ static void emit_insn(struct brw_vs_compile *c,
       emit_math1(c, BRW_MATH_FUNCTION_INV, dst, args[0], BRW_MATH_PRECISION_FULL);
       break;
    case TGSI_OPCODE_RSQ:
-      emit_math1(c, BRW_MATH_FUNCTION_RSQ, dst, args[0], BRW_MATH_PRECISION_FULL);
+      emit_math1(c, BRW_MATH_FUNCTION_RSQ, dst, 
+                 brw_swizzle(args[0], 0,0,0,0), BRW_MATH_PRECISION_FULL);
       break;
    case TGSI_OPCODE_SEQ:
       emit_seq(p, dst, args[0], args[1]);
@@ -1460,7 +1517,7 @@ static void emit_insn(struct brw_vs_compile *c,
 
       c->loop_depth--;
 
-      if (c->chipset.is_igdng)
+      if (brw->gen == 5)
         br = 2;
 
       inst0 = inst1 = brw_WHILE(p, c->loop_inst[c->loop_depth]);
@@ -1548,8 +1605,6 @@ void brw_vs_emit(struct brw_vs_compile *c)
    struct brw_instruction *end_inst, *last_inst;
    struct tgsi_parse_context parse;
    struct tgsi_full_instruction *inst;
-   boolean done = FALSE;
-   int i;
 
    if (BRW_DEBUG & DEBUG_VS)
       tgsi_dump(c->vp->tokens, 0); 
@@ -1559,37 +1614,6 @@ void brw_vs_emit(struct brw_vs_compile *c)
    brw_set_compression_control(p, BRW_COMPRESSION_NONE);
    brw_set_access_mode(p, BRW_ALIGN_16);
    
-   /* Inputs */
-   tgsi_parse_init( &parse, tokens );
-   while( !tgsi_parse_end_of_tokens( &parse ) ) {
-      tgsi_parse_token( &parse );
-
-      switch( parse.FullToken.Token.Type ) {
-      case TGSI_TOKEN_TYPE_DECLARATION:
-        /* Nothing to do -- using info from tgsi_scan().
-         */
-         break;
-
-      case TGSI_TOKEN_TYPE_IMMEDIATE: {
-        static const float id[4] = {0,0,0,1};
-        const float *imm = &parse.FullToken.FullImmediate.u[i].Float;
-        unsigned size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1;
-
-        for (i = 0; i < size; i++)
-           c->immediate[c->nr_immediates][i] = imm[i];
-
-        for ( ; i < 4; i++)
-           c->immediate[c->nr_immediates][i] = id[i];
-
-        c->nr_immediates++;
-        break;
-      }
-
-      case TGSI_TOKEN_TYPE_INSTRUCTION:
-        done = 1;
-        break;
-      }
-   }
 
    /* Static register allocation
     */
@@ -1631,6 +1655,6 @@ void brw_vs_emit(struct brw_vs_compile *c)
 
    if (BRW_DEBUG & DEBUG_VS) {
       debug_printf("vs-native:\n");
-      brw_disasm(stderr, p->store, p->nr_insn);
+      brw_disasm(stderr, p->store, p->nr_insn, p->brw->gen);
    }
 }