i965: Fix new FS gen6 interpolation for sparsely-populated arrays.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_fs.cpp
index f42c4696410553725c278839fee5bcf0b74af538..bc49ee8fe0d95a5cc35962c45145e0983b441529 100644 (file)
@@ -118,6 +118,7 @@ brw_compile_shader(GLcontext *ctx, struct gl_shader *shader)
 GLboolean
 brw_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
 {
+   struct intel_context *intel = intel_context(ctx);
    if (using_new_fs == -1)
       using_new_fs = getenv("INTEL_NEW_FS") != NULL;
 
@@ -139,6 +140,7 @@ brw_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
         do_sub_to_add_neg(shader->ir);
         do_explog_to_explog2(shader->ir);
         do_lower_texture_projection(shader->ir);
+        brw_do_cubemap_normalize(shader->ir);
 
         do {
            progress = false;
@@ -162,6 +164,9 @@ brw_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
                                                   GL_TRUE, /* temp */
                                                   GL_TRUE /* uniform */
                                                   ) || progress;
+           if (intel->gen == 6) {
+              progress = do_if_to_cond_assign(shader->ir) || progress;
+           }
         } while (progress);
 
         validate_ir_tree(shader->ir);
@@ -324,6 +329,7 @@ public:
       this->sampler = 0;
       this->target = 0;
       this->eot = false;
+      this->header_present = false;
       this->shadow_compare = false;
    }
 
@@ -376,6 +382,7 @@ public:
    int sampler;
    int target; /**< MRT target. */
    bool eot;
+   bool header_present;
    bool shadow_compare;
 
    /** @{
@@ -420,7 +427,10 @@ public:
       this->virtual_grf_array_size = 0;
       this->virtual_grf_def = NULL;
       this->virtual_grf_use = NULL;
+
+      this->kill_emitted = false;
    }
+
    ~fs_visitor()
    {
       talloc_free(this->mem_ctx);
@@ -469,8 +479,9 @@ public:
    void generate_ddy(fs_inst *inst, struct brw_reg dst, struct brw_reg src);
 
    void emit_dummy_fs();
-   void emit_fragcoord_interpolation(ir_variable *ir);
-   void emit_general_interpolation(ir_variable *ir);
+   fs_reg *emit_fragcoord_interpolation(ir_variable *ir);
+   fs_reg *emit_frontfacing_interpolation(ir_variable *ir);
+   fs_reg *emit_general_interpolation(ir_variable *ir);
    void emit_interpolation_setup_gen4();
    void emit_interpolation_setup_gen6();
    fs_inst *emit_texture_gen4(ir_texture *ir, fs_reg dst, fs_reg coordinate);
@@ -503,6 +514,7 @@ public:
    ir_variable *frag_color, *frag_data, *frag_depth;
    int first_non_payload_grf;
    int urb_setup[FRAG_ATTRIB_MAX];
+   bool kill_emitted;
 
    /** @{ debug annotation info */
    const char *current_annotation;
@@ -715,7 +727,7 @@ fs_visitor::setup_builtin_uniform_values(ir_variable *ir)
    }
 }
 
-void
+fs_reg *
 fs_visitor::emit_fragcoord_interpolation(ir_variable *ir)
 {
    fs_reg *reg = new(this->mem_ctx) fs_reg(this, ir->type);
@@ -755,11 +767,10 @@ fs_visitor::emit_fragcoord_interpolation(ir_variable *ir)
    /* gl_FragCoord.w: Already set up in emit_interpolation */
    emit(fs_inst(BRW_OPCODE_MOV, wpos, this->wpos_w));
 
-   hash_table_insert(this->variable_ht, reg, ir);
+   return reg;
 }
 
-
-void
+fs_reg *
 fs_visitor::emit_general_interpolation(ir_variable *ir)
 {
    fs_reg *reg = new(this->mem_ctx) fs_reg(this, ir->type);
@@ -802,20 +813,57 @@ fs_visitor::emit_general_interpolation(ir_variable *ir)
                         fs_reg(interp)));
            attr.reg_offset++;
         }
-        attr.reg_offset -= type->vector_elements;
 
-        for (unsigned int c = 0; c < type->vector_elements; c++) {
-           emit(fs_inst(BRW_OPCODE_MUL,
-                        attr,
-                        attr,
-                        this->pixel_w));
-           attr.reg_offset++;
+        if (intel->gen < 6) {
+           attr.reg_offset -= type->vector_elements;
+           for (unsigned int c = 0; c < type->vector_elements; c++) {
+              emit(fs_inst(BRW_OPCODE_MUL,
+                           attr,
+                           attr,
+                           this->pixel_w));
+              attr.reg_offset++;
+           }
         }
         location++;
       }
    }
 
-   hash_table_insert(this->variable_ht, reg, ir);
+   return reg;
+}
+
+fs_reg *
+fs_visitor::emit_frontfacing_interpolation(ir_variable *ir)
+{
+   fs_reg *reg = new(this->mem_ctx) fs_reg(this, ir->type);
+
+   /* The frontfacing comes in as a bit in the thread payload. */
+   if (intel->gen >= 6) {
+      emit(fs_inst(BRW_OPCODE_ASR,
+                  *reg,
+                  fs_reg(retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_D)),
+                  fs_reg(15)));
+      emit(fs_inst(BRW_OPCODE_NOT,
+                  *reg,
+                  *reg));
+      emit(fs_inst(BRW_OPCODE_AND,
+                  *reg,
+                  *reg,
+                  fs_reg(1)));
+   } else {
+      fs_reg *reg = new(this->mem_ctx) fs_reg(this, ir->type);
+      struct brw_reg r1_6ud = retype(brw_vec1_grf(1, 6), BRW_REGISTER_TYPE_UD);
+      /* bit 31 is "primitive is back face", so checking < (1 << 31) gives
+       * us front face
+       */
+      fs_inst *inst = emit(fs_inst(BRW_OPCODE_CMP,
+                                  *reg,
+                                  fs_reg(r1_6ud),
+                                  fs_reg(1u << 31)));
+      inst->conditional_mod = BRW_CONDITIONAL_L;
+      emit(fs_inst(BRW_OPCODE_AND, *reg, *reg, fs_reg(1u)));
+   }
+
+   return reg;
 }
 
 void
@@ -836,24 +884,15 @@ fs_visitor::visit(ir_variable *ir)
 
    if (ir->mode == ir_var_in) {
       if (!strcmp(ir->name, "gl_FragCoord")) {
-        emit_fragcoord_interpolation(ir);
-        return;
+        reg = emit_fragcoord_interpolation(ir);
       } else if (!strcmp(ir->name, "gl_FrontFacing")) {
-        reg = new(this->mem_ctx) fs_reg(this, ir->type);
-        struct brw_reg r1_6ud = retype(brw_vec1_grf(1, 6), BRW_REGISTER_TYPE_UD);
-        /* bit 31 is "primitive is back face", so checking < (1 << 31) gives
-         * us front face
-         */
-        fs_inst *inst = emit(fs_inst(BRW_OPCODE_CMP,
-                                     *reg,
-                                     fs_reg(r1_6ud),
-                                     fs_reg(1u << 31)));
-        inst->conditional_mod = BRW_CONDITIONAL_L;
-        emit(fs_inst(BRW_OPCODE_AND, *reg, *reg, fs_reg(1u)));
+        reg = emit_frontfacing_interpolation(ir);
       } else {
-        emit_general_interpolation(ir);
-        return;
+        reg = emit_general_interpolation(ir);
       }
+      assert(reg);
+      hash_table_insert(this->variable_ht, reg, ir);
+      return;
    }
 
    if (ir->mode == ir_var_uniform) {
@@ -1509,6 +1548,7 @@ fs_visitor::visit(ir_discard *ir)
    assert(ir->condition == NULL); /* FINISHME */
 
    emit(fs_inst(FS_OPCODE_DISCARD, temp, temp));
+   kill_emitted = true;
 }
 
 void
@@ -1843,10 +1883,19 @@ void
 fs_visitor::emit_fb_writes()
 {
    this->current_annotation = "FB write header";
+   GLboolean header_present = GL_TRUE;
    int nr = 0;
 
-   /* m0, m1 header */
-   nr += 2;
+   if (intel->gen >= 6 &&
+       !this->kill_emitted &&
+       c->key.nr_color_regions == 1) {
+      header_present = false;
+   }
+
+   if (header_present) {
+      /* m0, m1 header */
+      nr += 2;
+   }
 
    if (c->key.aa_dest_stencil_reg) {
       emit(fs_inst(BRW_OPCODE_MOV, fs_reg(MRF, nr++),
@@ -1904,6 +1953,7 @@ fs_visitor::emit_fb_writes()
       inst->mlen = nr;
       if (target == c->key.nr_color_regions - 1)
         inst->eot = true;
+      inst->header_present = header_present;
    }
 
    if (c->key.nr_color_regions == 0) {
@@ -1911,6 +1961,7 @@ fs_visitor::emit_fb_writes()
                                   reg_undef, reg_undef));
       inst->mlen = nr;
       inst->eot = true;
+      inst->header_present = header_present;
    }
 
    this->current_annotation = NULL;
@@ -1929,19 +1980,23 @@ fs_visitor::generate_fb_write(fs_inst *inst)
    brw_set_mask_control(p, BRW_MASK_DISABLE);
    brw_set_compression_control(p, BRW_COMPRESSION_NONE);
 
-   if (intel->gen >= 6) {
+   if (inst->header_present) {
+      if (intel->gen >= 6) {
+        brw_MOV(p,
+                brw_message_reg(0),
+                brw_vec8_grf(0, 0));
+        implied_header = brw_null_reg();
+      } else {
+        implied_header = retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW);
+      }
+
       brw_MOV(p,
-             brw_message_reg(0),
-             brw_vec8_grf(0, 0));
-      implied_header = brw_null_reg();
+             brw_message_reg(1),
+             brw_vec8_grf(1, 0));
    } else {
-      implied_header = retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW);
+      implied_header = brw_null_reg();
    }
 
-   brw_MOV(p,
-          brw_message_reg(1),
-          brw_vec8_grf(1, 0));
-
    brw_pop_insn_state(p);
 
    brw_fb_WRITE(p,
@@ -2030,7 +2085,7 @@ fs_visitor::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src)
    int rlen = 4;
    uint32_t simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD8;
 
-   if (intel->gen == 5) {
+   if (intel->gen >= 5) {
       switch (inst->opcode) {
       case FS_OPCODE_TEX:
         if (inst->shadow_compare) {
@@ -2208,8 +2263,7 @@ fs_visitor::calculate_urb_setup()
    /* Figure out where each of the incoming setup attributes lands. */
    if (intel->gen >= 6) {
       for (unsigned int i = 0; i < FRAG_ATTRIB_MAX; i++) {
-        if (i == FRAG_ATTRIB_WPOS ||
-            (brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(i))) {
+        if (brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(i)) {
            urb_setup[i] = urb_next++;
         }
       }
@@ -2548,8 +2602,6 @@ fs_visitor::propagate_constants()
 {
    bool progress = false;
 
-   return false;
-
    foreach_iter(exec_list_iterator, iter, this->instructions) {
       fs_inst *inst = (fs_inst *)iter.get();
 
@@ -2609,6 +2661,11 @@ fs_visitor::propagate_constants()
                  scan_inst->src[1] = inst->src[0];
               }
               break;
+           case BRW_OPCODE_CMP:
+              if (i == 1) {
+                 scan_inst->src[i] = inst->src[0];
+                 progress = true;
+              }
            }
         }
 
@@ -2782,6 +2839,18 @@ fs_visitor::generate_code()
       case BRW_OPCODE_XOR:
         brw_XOR(p, dst, src[0], src[1]);
         break;
+      case BRW_OPCODE_NOT:
+        brw_NOT(p, dst, src[0]);
+        break;
+      case BRW_OPCODE_ASR:
+        brw_ASR(p, dst, src[0], src[1]);
+        break;
+      case BRW_OPCODE_SHR:
+        brw_SHR(p, dst, src[0], src[1]);
+        break;
+      case BRW_OPCODE_SHL:
+        brw_SHL(p, dst, src[0], src[1]);
+        break;
 
       case BRW_OPCODE_CMP:
         brw_CMP(p, dst, inst->conditional_mod, src[0], src[1]);