i965: Use sample barycentric coordinates with per sample shading
[mesa.git] / src / mesa / drivers / dri / i965 / brw_fs_reg_allocate.cpp
index 157c9ae4ffa91c1160a62a6b1f149e4f798e025d..2494b117e57506e2c9d4336148600e17a914e97a 100644 (file)
@@ -78,7 +78,7 @@ brw_alloc_reg_set(struct brw_context *brw, int reg_width)
 
    /* The registers used to make up almost all values handled in the compiler
     * are a scalar value occupying a single register (or 2 registers in the
-    * case of 16-wide, which is handled by dividing base_reg_count by 2 and
+    * case of SIMD16, which is handled by dividing base_reg_count by 2 and
     * multiplying allocated register numbers by 2).  Things that were
     * aggregates of scalar values at the GLSL level were split to scalar
     * values by split_virtual_grfs().
@@ -103,7 +103,8 @@ brw_alloc_reg_set(struct brw_context *brw, int reg_width)
    int class_sizes[BRW_MAX_MRF];
 
    if (brw->gen >= 7) {
-      for (class_count = 0; class_count < 11; class_count++)
+      for (class_count = 0; class_count < MAX_SAMPLER_MESSAGE_SIZE;
+           class_count++)
          class_sizes[class_count] = class_count + 1;
    } else {
       for (class_count = 0; class_count < 4; class_count++)
@@ -225,7 +226,7 @@ count_to_loop_end(fs_inst *do_inst)
  * nr_payload_regs+curb_read_lengh..first_non_payload_grf-1: setup coefficients.
  *
  * And we have payload_node_count nodes covering these registers in order
- * (note that in 16-wide, a node is two registers).
+ * (note that in SIMD16, a node is two registers).
  */
 void
 fs_visitor::setup_payload_interference(struct ra_graph *g,
@@ -295,7 +296,7 @@ fs_visitor::setup_payload_interference(struct ra_graph *g,
          break;
 
       case FS_OPCODE_LINTERP:
-         /* On gen6+ in 16-wide, there are 4 adjacent registers (so 2 nodes)
+         /* On gen6+ in SIMD16, there are 4 adjacent registers (so 2 nodes)
           * used by PLN's sourcing of the deltas, while we list only the first
           * two in the arguments (1 node).  Pre-gen6, the deltas are computed
           * in normal VGRFs.
@@ -347,18 +348,20 @@ fs_visitor::setup_payload_interference(struct ra_graph *g,
 }
 
 /**
- * Sets interference between virtual GRFs and usage of the high GRFs for SEND
- * messages (treated as MRFs in code generation).
+ * Sets the mrf_used array to indicate which MRFs are used by the shader IR
+ *
+ * This is used in assign_regs() to decide which of the GRFs that we use as
+ * MRFs on gen7 get normally register allocated, and in register spilling to
+ * see if we can actually use MRFs to do spills without overwriting normal MRF
+ * contents.
  */
 void
-fs_visitor::setup_mrf_hack_interference(struct ra_graph *g, int first_mrf_node)
+fs_visitor::get_used_mrfs(bool *mrf_used)
 {
-   int mrf_count = BRW_MAX_GRF - GEN7_MRF_HACK_START;
    int reg_width = dispatch_width / 8;
 
-   /* Identify all the MRFs used in the program. */
-   bool mrf_used[mrf_count];
-   memset(mrf_used, 0, sizeof(mrf_used));
+   memset(mrf_used, 0, BRW_MAX_MRF * sizeof(bool));
+
    foreach_list(node, &this->instructions) {
       fs_inst *inst = (fs_inst *)node;
 
@@ -380,9 +383,22 @@ fs_visitor::setup_mrf_hack_interference(struct ra_graph *g, int first_mrf_node)
          }
       }
    }
+}
+
+/**
+ * Sets interference between virtual GRFs and usage of the high GRFs for SEND
+ * messages (treated as MRFs in code generation).
+ */
+void
+fs_visitor::setup_mrf_hack_interference(struct ra_graph *g, int first_mrf_node)
+{
+   int reg_width = dispatch_width / 8;
 
-   for (int i = 0; i < mrf_count; i++) {
-      /* Mark each payload reg node as being allocated to its physical register.
+   bool mrf_used[BRW_MAX_MRF];
+   get_used_mrfs(mrf_used);
+
+   for (int i = 0; i < BRW_MAX_MRF; i++) {
+      /* Mark each MRF reg node as being allocated to its physical register.
        *
        * The alternative would be to have per-physical-register classes, which
        * would just be silly.
@@ -402,10 +418,10 @@ fs_visitor::setup_mrf_hack_interference(struct ra_graph *g, int first_mrf_node)
 }
 
 bool
-fs_visitor::assign_regs()
+fs_visitor::assign_regs(bool allow_spilling)
 {
    /* Most of this allocation was written for a reg_width of 1
-    * (dispatch_width == 8).  In extending to 16-wide, the code was
+    * (dispatch_width == 8).  In extending to SIMD16, the code was
     * left in place and it was converted to have the hardware
     * registers it's allocating be contiguous physical pairs of regs
     * for reg_width == 2.
@@ -461,6 +477,17 @@ fs_visitor::assign_regs()
    if (brw->gen >= 7)
       setup_mrf_hack_interference(g, first_mrf_hack_node);
 
+   /* Debug of register spilling: Go spill everything. */
+   if (0) {
+      int reg = choose_spill_reg(g);
+
+      if (reg != -1) {
+         spill_reg(reg);
+         ralloc_free(g);
+         return false;
+      }
+   }
+
    if (!ra_allocate_no_spills(g)) {
       /* Failed to allocate registers.  Spill a reg, and the caller will
        * loop back into here to try again.
@@ -470,14 +497,10 @@ fs_visitor::assign_regs()
       if (reg == -1) {
          fail("no register to spill:\n");
          dump_instructions();
-      } else if (dispatch_width == 16) {
-        fail("Failure to register allocate.  Reduce number of live scalar "
-              "values to avoid this.");
-      } else {
-        spill_reg(reg);
+      } else if (allow_spilling) {
+         spill_reg(reg);
       }
 
-
       ralloc_free(g);
 
       return false;
@@ -516,20 +539,26 @@ fs_visitor::emit_unspill(fs_inst *inst, fs_reg dst, uint32_t spill_offset,
                          int count)
 {
    for (int i = 0; i < count; i++) {
-      fs_inst *unspill_inst = new(mem_ctx) fs_inst(FS_OPCODE_UNSPILL, dst);
+      /* The gen7 descriptor-based offset is 12 bits of HWORD units. */
+      bool gen7_read = brw->gen >= 7 && spill_offset < (1 << 12) * REG_SIZE;
+
+      fs_inst *unspill_inst =
+         new(mem_ctx) fs_inst(gen7_read ?
+                              SHADER_OPCODE_GEN7_SCRATCH_READ :
+                              SHADER_OPCODE_GEN4_SCRATCH_READ,
+                              dst);
       unspill_inst->offset = spill_offset;
       unspill_inst->ir = inst->ir;
       unspill_inst->annotation = inst->annotation;
 
-      /* Choose a MRF that won't conflict with an MRF that's live across the
-       * spill.  Nothing else will make it up to MRF 14/15.
-       */
-      unspill_inst->base_mrf = 14;
-      unspill_inst->mlen = 1; /* header contains offset */
+      if (!gen7_read) {
+         unspill_inst->base_mrf = 14;
+         unspill_inst->mlen = 1; /* header contains offset */
+      }
       inst->insert_before(unspill_inst);
 
       dst.reg_offset++;
-      spill_offset += REG_SIZE;
+      spill_offset += dispatch_width * sizeof(float);
    }
 }
 
@@ -587,12 +616,13 @@ fs_visitor::choose_spill_reg(struct ra_graph *g)
         loop_scale /= 10;
         break;
 
-      case FS_OPCODE_SPILL:
+      case SHADER_OPCODE_GEN4_SCRATCH_WRITE:
         if (inst->src[0].file == GRF)
            no_spill[inst->src[0].reg] = true;
         break;
 
-      case FS_OPCODE_UNSPILL:
+      case SHADER_OPCODE_GEN4_SCRATCH_READ:
+      case SHADER_OPCODE_GEN7_SCRATCH_READ:
         if (inst->dst.file == GRF)
            no_spill[inst->dst.reg] = true;
         break;
@@ -613,10 +643,34 @@ fs_visitor::choose_spill_reg(struct ra_graph *g)
 void
 fs_visitor::spill_reg(int spill_reg)
 {
+   int reg_size = dispatch_width * sizeof(float);
    int size = virtual_grf_sizes[spill_reg];
    unsigned int spill_offset = c->last_scratch;
    assert(ALIGN(spill_offset, 16) == spill_offset); /* oword read/write req. */
-   c->last_scratch += size * REG_SIZE;
+   int spill_base_mrf = dispatch_width > 8 ? 13 : 14;
+
+   /* Spills may use MRFs 13-15 in the SIMD16 case.  Our texturing is done
+    * using up to 11 MRFs starting from either m1 or m2, and fb writes can use
+    * up to m13 (gen6+ simd16: 2 header + 8 color + 2 src0alpha + 2 omask) or
+    * m15 (gen4-5 simd16: 2 header + 8 color + 1 aads + 2 src depth + 2 dst
+    * depth), starting from m1.  In summary: We may not be able to spill in
+    * SIMD16 mode, because we'd stomp the FB writes.
+    */
+   if (!spilled_any_registers) {
+      bool mrf_used[BRW_MAX_MRF];
+      get_used_mrfs(mrf_used);
+
+      for (int i = spill_base_mrf; i < BRW_MAX_MRF; i++) {
+         if (mrf_used[i]) {
+            fail("Register spilling not supported with m%d used", i);
+          return;
+         }
+      }
+
+      spilled_any_registers = true;
+   }
+
+   c->last_scratch += size * reg_size;
 
    /* Generate spill/unspill instructions for the objects being
     * spilled.  Right now, we spill or unspill the whole thing to a
@@ -630,20 +684,20 @@ fs_visitor::spill_reg(int spill_reg)
         if (inst->src[i].file == GRF &&
             inst->src[i].reg == spill_reg) {
             int regs_read = inst->regs_read(this, i);
+            int subset_spill_offset = (spill_offset +
+                                       reg_size * inst->src[i].reg_offset);
 
             inst->src[i].reg = virtual_grf_alloc(regs_read);
             inst->src[i].reg_offset = 0;
 
-            emit_unspill(inst, inst->src[i],
-                         spill_offset + REG_SIZE * inst->src[i].reg_offset,
-                         regs_read);
+            emit_unspill(inst, inst->src[i], subset_spill_offset, regs_read);
         }
       }
 
       if (inst->dst.file == GRF &&
          inst->dst.reg == spill_reg) {
          int subset_spill_offset = (spill_offset +
-                                    REG_SIZE * inst->dst.reg_offset);
+                                    reg_size * inst->dst.reg_offset);
          inst->dst.reg = virtual_grf_alloc(inst->regs_written);
          inst->dst.reg_offset = 0;
 
@@ -663,14 +717,15 @@ fs_visitor::spill_reg(int spill_reg)
         spill_src.smear = -1;
 
         for (int chan = 0; chan < inst->regs_written; chan++) {
-           fs_inst *spill_inst = new(mem_ctx) fs_inst(FS_OPCODE_SPILL,
-                                                      reg_null_f, spill_src);
+           fs_inst *spill_inst =
+               new(mem_ctx) fs_inst(SHADER_OPCODE_GEN4_SCRATCH_WRITE,
+                                    reg_null_f, spill_src);
            spill_src.reg_offset++;
-           spill_inst->offset = subset_spill_offset + chan * REG_SIZE;
+           spill_inst->offset = subset_spill_offset + chan * reg_size;
            spill_inst->ir = inst->ir;
            spill_inst->annotation = inst->annotation;
-           spill_inst->base_mrf = 14;
-           spill_inst->mlen = 2; /* header, value */
+           spill_inst->mlen = 1 + dispatch_width / 8; /* header, value */
+           spill_inst->base_mrf = spill_base_mrf;
            inst->insert_after(spill_inst);
         }
       }