i965: Fix new FS gen6 interpolation for sparsely-populated arrays.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_fs.cpp
index 7327c3a700eee16703ae5184da31d71bd94639c6..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);
@@ -474,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);
@@ -721,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);
@@ -761,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);
@@ -808,9 +813,9 @@ fs_visitor::emit_general_interpolation(ir_variable *ir)
                         fs_reg(interp)));
            attr.reg_offset++;
         }
-        attr.reg_offset -= type->vector_elements;
 
         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,
@@ -823,7 +828,42 @@ fs_visitor::emit_general_interpolation(ir_variable *ir)
       }
    }
 
-   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
@@ -844,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) {
@@ -2054,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) {
@@ -2232,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++;
         }
       }
@@ -2809,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]);