Merge branch '7.8'
[mesa.git] / src / gallium / drivers / i965 / brw_vs_emit.c
index d86e2104d8dd2c7d281dd7b9d213a8fc262501a3..5dcbd597ddcaf1860c3efada8a98d5e10ad02592 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,7 @@ 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;
+   GLuint i, reg = 0, subreg = 0, mrf;
    int attributes_in_vue;
 
    /* Determine whether to use a real constant buffer or use a block
@@ -82,15 +124,15 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c )
     * works if everything fits in the GRF.
     * XXX this heuristic/check may need some fine tuning...
     */
-   if (c->vp->info.file_max[TGSI_FILE_CONSTANT] +
-       c->vp->info.file_max[TGSI_FILE_IMMEDIATE] +
-       c->vp->info.file_max[TGSI_FILE_TEMPORARY] + 21 > BRW_MAX_GRF)
+   if (c->vp->info.file_max[TGSI_FILE_CONSTANT] + 1 +
+       c->vp->info.file_max[TGSI_FILE_IMMEDIATE] + 1 +
+       c->vp->info.file_max[TGSI_FILE_TEMPORARY] + 1 + 21 > BRW_MAX_GRF)
       c->vp->use_const_buffer = GL_TRUE;
    else {
       /* XXX: immediates can go elsewhere if necessary:
        */
-      assert(c->vp->info.file_max[TGSI_FILE_IMMEDIATE] +
-            c->vp->info.file_max[TGSI_FILE_TEMPORARY] + 21 <= BRW_MAX_GRF);
+      assert(c->vp->info.file_max[TGSI_FILE_IMMEDIATE] + 1 +
+            c->vp->info.file_max[TGSI_FILE_TEMPORARY] + 1 + 21 <= BRW_MAX_GRF);
 
       c->vp->use_const_buffer = GL_FALSE;
    }
@@ -105,33 +147,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,69 +212,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 = 0;
-   c->first_output = reg;
-   c->first_overflow_output = 0;
+   c->nr_outputs = c->prog_data.nr_outputs;
 
    if (c->chipset.is_igdng)
       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:
     */
-   c->nr_outputs = c->prog_data.nr_outputs;
-   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();
       }
    }     
 
@@ -244,15 +296,19 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c )
       }
    }
 
+#if 0
    for (i = 0; i < 128; i++) {
       if (c->output_regs[i].used_in_src) {
          c->output_regs[i].reg = brw_vec8_grf(reg, 0);
          reg++;
       }
    }
+#endif
 
-   c->stack =  brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, reg, 0);
-   reg += 2;
+   if (c->vp->has_flow_control) {
+      c->stack =  brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, reg, 0);
+      reg += 2;
+   }
 
    /* Some opcodes need an internal temporary:
     */
@@ -852,6 +908,7 @@ get_constant(struct brw_vs_compile *c,
 }
 
 
+#if 0
 
 /* TODO: relative addressing!
  */
@@ -880,6 +937,8 @@ static struct brw_reg get_reg( struct brw_vs_compile *c,
    }
 }
 
+#endif
+
 
 /**
  * Indirect addressing:  get reg[[arg] + offset].
@@ -998,22 +1057,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
     */
@@ -1069,15 +1128,9 @@ static void emit_vertex_write( struct brw_vs_compile *c)
    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 */
@@ -1164,7 +1217,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 */
@@ -1179,19 +1232,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,
@@ -1200,11 +1256,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);
    }
 }
@@ -1281,7 +1337,7 @@ 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_reg args[3], dst;
    GLuint i;
@@ -1294,7 +1350,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
@@ -1302,9 +1358,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
     */
@@ -1390,7 +1446,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]);
@@ -1545,8 +1602,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); 
@@ -1556,42 +1611,14 @@ 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
     */
    brw_vs_alloc_regs(c);
-   brw_MOV(p, get_addr_reg(c->stack_index), brw_address(c->stack));
+
+   if (c->vp->has_flow_control) {
+      brw_MOV(p, get_addr_reg(c->stack_index), brw_address(c->stack));
+   }
 
    /* Instructions
     */
@@ -1624,8 +1651,6 @@ void brw_vs_emit(struct brw_vs_compile *c)
    post_vs_emit(c, end_inst, last_inst);
 
    if (BRW_DEBUG & DEBUG_VS) {
-      int i;
-
       debug_printf("vs-native:\n");
       brw_disasm(stderr, p->store, p->nr_insn);
    }