i965: Don't emit saturates for instructions without destinations.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_fs_fp.cpp
index 49eaf0544069a768435a8721e8fcb6a6f5e670ca..d22de0e514554a8d007198fa9f6fd81ae4fd458a 100644 (file)
@@ -57,7 +57,7 @@ void
 fs_visitor::emit_fp_minmax(const prog_instruction *fpi,
                            fs_reg dst, fs_reg src0, fs_reg src1)
 {
-   uint32_t conditionalmod;
+   enum brw_conditional_mod conditionalmod;
    if (fpi->Opcode == OPCODE_MIN)
       conditionalmod = BRW_CONDITIONAL_L;
    else
@@ -72,7 +72,7 @@ fs_visitor::emit_fp_minmax(const prog_instruction *fpi,
 }
 
 void
-fs_visitor::emit_fp_sop(uint32_t conditional_mod,
+fs_visitor::emit_fp_sop(enum brw_conditional_mod conditional_mod,
                         const struct prog_instruction *fpi,
                         fs_reg dst, fs_reg src0, fs_reg src1,
                         fs_reg one)
@@ -105,7 +105,7 @@ fs_visitor::emit_fp_scalar_math(enum opcode opcode,
                                 const struct prog_instruction *fpi,
                                 fs_reg dst, fs_reg src)
 {
-   fs_reg temp = fs_reg(this, glsl_type::float_type);
+   fs_reg temp = vgrf(glsl_type::float_type);
    emit_math(opcode, temp, src);
    emit_fp_scalar_write(fpi, dst, temp);
 }
@@ -115,8 +115,6 @@ fs_visitor::emit_fragment_program_code()
 {
    setup_fp_regs();
 
-   fs_reg null = fs_reg(brw_null_reg());
-
    /* Keep a reg with 1.0 around, for reuse by emit_fp_sop so that it can just
     * be:
     *
@@ -127,22 +125,20 @@ fs_visitor::emit_fragment_program_code()
     * mov    dst 0.0
     * mov.f0 dst 1.0
     */
-   fs_reg one = fs_reg(this, glsl_type::float_type);
+   fs_reg one = vgrf(glsl_type::float_type);
    emit(MOV(one, fs_reg(1.0f)));
 
    for (unsigned int insn = 0; insn < prog->NumInstructions; insn++) {
       const struct prog_instruction *fpi = &prog->Instructions[insn];
       base_ir = fpi;
 
-      //_mesa_print_instruction(fpi);
-
       fs_reg dst;
       fs_reg src[3];
 
       /* We always emit into a temporary destination register to avoid
        * aliasing issues.
        */
-      dst = fs_reg(this, glsl_type::vec4_type);
+      dst = vgrf(glsl_type::vec4_type);
 
       for (int i = 0; i < 3; i++)
          src[i] = get_fp_src_reg(&fpi->SrcReg[i]);
@@ -163,7 +159,7 @@ fs_visitor::emit_fragment_program_code()
             if (fpi->DstReg.WriteMask & (1 << i)) {
                fs_inst *inst;
 
-               emit(CMP(null, offset(src[0], i), fs_reg(0.0f),
+               emit(CMP(reg_null_f, offset(src[0], i), fs_reg(0.0f),
                         BRW_CONDITIONAL_L));
 
                inst = emit(BRW_OPCODE_SEL, offset(dst, i),
@@ -181,8 +177,8 @@ fs_visitor::emit_fragment_program_code()
       case OPCODE_DP3:
       case OPCODE_DP4:
       case OPCODE_DPH: {
-         fs_reg mul = fs_reg(this, glsl_type::float_type);
-         fs_reg acc = fs_reg(this, glsl_type::float_type);
+         fs_reg mul = vgrf(glsl_type::float_type);
+         fs_reg acc = vgrf(glsl_type::float_type);
          int count;
 
          switch (fpi->Opcode) {
@@ -190,7 +186,7 @@ fs_visitor::emit_fragment_program_code()
          case OPCODE_DP3: count = 3; break;
          case OPCODE_DP4: count = 4; break;
          case OPCODE_DPH: count = 3; break;
-         default: assert(!"not reached"); count = 0; break;
+         default: unreachable("not reached");
          }
 
          emit(MUL(acc, offset(src[0], 0), offset(src[1], 0)));
@@ -250,8 +246,8 @@ fs_visitor::emit_fragment_program_code()
              * undiscarded pixels, and updates just those pixels to be
              * turned off.
              */
-            fs_inst *cmp = emit(CMP(null, offset(src[0], i), fs_reg(0.0f),
-                                    BRW_CONDITIONAL_GE));
+            fs_inst *cmp = emit(CMP(reg_null_f, offset(src[0], i),
+                                    fs_reg(0.0f), BRW_CONDITIONAL_GE));
             cmp->predicate = BRW_PREDICATE_NORMAL;
             cmp->flag_subreg = 1;
          }
@@ -283,7 +279,7 @@ fs_visitor::emit_fragment_program_code()
 
          if (fpi->DstReg.WriteMask & WRITEMASK_YZ) {
             fs_inst *inst;
-            emit(CMP(null, offset(src[0], 0), fs_reg(0.0f),
+            emit(CMP(reg_null_f, offset(src[0], 0), fs_reg(0.0f),
                      BRW_CONDITIONAL_LE));
 
             if (fpi->DstReg.WriteMask & WRITEMASK_Y) {
@@ -320,9 +316,14 @@ fs_visitor::emit_fragment_program_code()
       case OPCODE_MAD:
          for (int i = 0; i < 4; i++) {
             if (fpi->DstReg.WriteMask & (1 << i)) {
-               fs_reg temp = fs_reg(this, glsl_type::float_type);
-               emit(MUL(temp, offset(src[0], i), offset(src[1], i)));
-               emit(ADD(offset(dst, i), temp, offset(src[2], i)));
+               if (brw->gen >= 6) {
+                  emit(MAD(offset(dst, i), offset(src[2], i),
+                           offset(src[1], i), offset(src[0], i)));
+               } else {
+                  fs_reg temp = vgrf(glsl_type::float_type);
+                  emit(MUL(temp, offset(src[0], i), offset(src[1], i)));
+                  emit(ADD(offset(dst, i), temp, offset(src[2], i)));
+               }
             }
          }
          break;
@@ -344,7 +345,7 @@ fs_visitor::emit_fragment_program_code()
          break;
 
       case OPCODE_POW: {
-         fs_reg temp = fs_reg(this, glsl_type::float_type);
+         fs_reg temp = vgrf(glsl_type::float_type);
          emit_math(SHADER_OPCODE_POW, temp, src[0], src[1]);
          emit_fp_scalar_write(fpi, dst, temp);
          break;
@@ -393,29 +394,23 @@ fs_visitor::emit_fragment_program_code()
       case OPCODE_TEX:
       case OPCODE_TXB:
       case OPCODE_TXP: {
-         /* We piggy-back on the GLSL IR support for texture setup.  To do so,
-          * we have to cook up an ir_texture that has the coordinate field
-          * with appropriate type, and shadow_comparitor set or not.  All the
-          * other properties of ir_texture are passed in as arguments to the
-          * emit_texture_gen* function.
-          */
-         ir_texture *ir = NULL;
-
+         ir_texture_opcode op;
          fs_reg lod;
          fs_reg dpdy;
          fs_reg coordinate = src[0];
          fs_reg shadow_c;
          fs_reg sample_index;
+         fs_reg texel_offset; /* No offsets; leave as BAD_FILE. */
 
          switch (fpi->Opcode) {
          case OPCODE_TEX:
-            ir = new(mem_ctx) ir_texture(ir_tex);
+            op = ir_tex;
             break;
          case OPCODE_TXP: {
-            ir = new(mem_ctx) ir_texture(ir_tex);
+            op = ir_tex;
 
-            coordinate = fs_reg(this, glsl_type::vec3_type);
-            fs_reg invproj = fs_reg(this, glsl_type::float_type);
+            coordinate = vgrf(glsl_type::vec3_type);
+            fs_reg invproj = vgrf(glsl_type::float_type);
             emit_math(SHADER_OPCODE_RCP, invproj, offset(src[0], 3));
             for (int i = 0; i < 3; i++) {
                emit(MUL(offset(coordinate, i),
@@ -424,39 +419,36 @@ fs_visitor::emit_fragment_program_code()
             break;
          }
          case OPCODE_TXB:
-            ir = new(mem_ctx) ir_texture(ir_txb);
+            op = ir_txb;
             lod = offset(src[0], 3);
             break;
          default:
-            assert(!"not reached");
-            break;
+            unreachable("not reached");
          }
 
-         ir->type = glsl_type::vec4_type;
-
-         const glsl_type *coordinate_type;
+         int coord_components;
          switch (fpi->TexSrcTarget) {
          case TEXTURE_1D_INDEX:
-            coordinate_type = glsl_type::float_type;
+            coord_components = 1;
             break;
 
          case TEXTURE_2D_INDEX:
          case TEXTURE_1D_ARRAY_INDEX:
          case TEXTURE_RECT_INDEX:
          case TEXTURE_EXTERNAL_INDEX:
-            coordinate_type = glsl_type::vec2_type;
+            coord_components = 2;
             break;
 
          case TEXTURE_3D_INDEX:
          case TEXTURE_2D_ARRAY_INDEX:
-            coordinate_type = glsl_type::vec3_type;
+            coord_components = 3;
             break;
 
          case TEXTURE_CUBE_INDEX: {
-            coordinate_type = glsl_type::vec3_type;
+            coord_components = 4;
 
-            fs_reg temp = fs_reg(this, glsl_type::float_type);
-            fs_reg cubecoord = fs_reg(this, glsl_type::vec3_type);
+            fs_reg temp = vgrf(glsl_type::float_type);
+            fs_reg cubecoord = vgrf(glsl_type::vec3_type);
             fs_reg abscoord = coordinate;
             abscoord.negate = false;
             abscoord.abs = true;
@@ -475,37 +467,21 @@ fs_visitor::emit_fragment_program_code()
          }
 
          default:
-            assert(!"not reached");
-            coordinate_type = glsl_type::vec2_type;
-            break;
+            unreachable("not reached");
          }
 
-         ir_constant_data junk_data;
-         ir->coordinate = new(mem_ctx) ir_constant(coordinate_type, &junk_data);
-
-         if (fpi->TexShadow) {
+         if (fpi->TexShadow)
             shadow_c = offset(coordinate, 2);
-            ir->shadow_comparitor = new(mem_ctx) ir_constant(0.0f);
-         }
-
-         coordinate = rescale_texcoord(ir, coordinate,
-                                       fpi->TexSrcTarget == TEXTURE_RECT_INDEX,
-                                       fpi->TexSrcUnit, fpi->TexSrcUnit);
 
-         fs_inst *inst;
-         if (brw->gen >= 7) {
-            inst = emit_texture_gen7(ir, dst, coordinate, shadow_c, lod, dpdy, sample_index, fs_reg(0u), fpi->TexSrcUnit);
-         } else if (brw->gen >= 5) {
-            inst = emit_texture_gen5(ir, dst, coordinate, shadow_c, lod, dpdy, sample_index);
-         } else {
-            inst = emit_texture_gen4(ir, dst, coordinate, shadow_c, lod, dpdy);
-         }
-
-         inst->sampler = fpi->TexSrcUnit;
-         inst->shadow_compare = fpi->TexShadow;
-
-         /* Reuse the GLSL swizzle_result() handler. */
-         swizzle_result(ir, dst, fpi->TexSrcUnit);
+         emit_texture(op, glsl_type::vec4_type, coordinate, coord_components,
+                      shadow_c, lod, dpdy, 0, sample_index,
+                      reg_undef, 0, /* offset, components */
+                      reg_undef, /* mcs */
+                      0, /* gather component */
+                      false, /* is cube array */
+                      fpi->TexSrcTarget == TEXTURE_RECT_INDEX,
+                      fpi->TexSrcUnit, fs_reg(fpi->TexSrcUnit),
+                      fpi->TexSrcUnit);
          dst = this->result;
 
          break;
@@ -524,7 +500,7 @@ fs_visitor::emit_fragment_program_code()
                int i1 = (i + 1) % 3;
                int i2 = (i + 2) % 3;
 
-               fs_reg temp = fs_reg(this, glsl_type::float_type);
+               fs_reg temp = vgrf(glsl_type::float_type);
                fs_reg neg_src1_1 = offset(src[1], i1);
                neg_src1_1.negate = !neg_src1_1.negate;
                emit(MUL(temp, offset(src[0], i2), neg_src1_1));
@@ -546,7 +522,7 @@ fs_visitor::emit_fragment_program_code()
       /* To handle saturates, we emit a MOV with a saturate bit, which
        * optimization should fold into the preceding instructions when safe.
        */
-      if (fpi->Opcode != OPCODE_END) {
+      if (_mesa_num_inst_dst_regs(fpi->Opcode) != 0) {
          fs_reg real_dst = get_fp_dst_reg(&fpi->DstReg);
 
          for (int i = 0; i < 4; i++) {
@@ -566,7 +542,7 @@ fs_visitor::emit_fragment_program_code()
     */
    this->current_annotation = "result.depth write";
    if (frag_depth.file != BAD_FILE) {
-      fs_reg temp = fs_reg(this, glsl_type::float_type);
+      fs_reg temp = vgrf(glsl_type::float_type);
       emit(MOV(temp, offset(frag_depth, 2)));
       frag_depth = temp;
    }
@@ -579,7 +555,7 @@ fs_visitor::setup_fp_regs()
    int num_temp = prog->NumTemporaries;
    fp_temp_regs = rzalloc_array(mem_ctx, fs_reg, num_temp);
    for (int i = 0; i < num_temp; i++)
-      fp_temp_regs[i] = fs_reg(this, glsl_type::vec4_type);
+      fp_temp_regs[i] = vgrf(glsl_type::vec4_type);
 
    /* PROGRAM_STATE_VAR etc. */
    if (dispatch_width == 8) {
@@ -587,7 +563,7 @@ fs_visitor::setup_fp_regs()
            p < prog->Parameters->NumParameters; p++) {
          for (unsigned int i = 0; i < 4; i++) {
             stage_prog_data->param[uniforms++] =
-               &prog->Parameters->ParameterValues[p][i].f;
+               &prog->Parameters->ParameterValues[p][i];
          }
       }
    }
@@ -595,28 +571,28 @@ fs_visitor::setup_fp_regs()
    fp_input_regs = rzalloc_array(mem_ctx, fs_reg, VARYING_SLOT_MAX);
    for (int i = 0; i < VARYING_SLOT_MAX; i++) {
       if (prog->InputsRead & BITFIELD64_BIT(i)) {
-         /* Make up a dummy instruction to reuse code for emitting
-          * interpolation.
-          */
-         ir_variable *ir = new(mem_ctx) ir_variable(glsl_type::vec4_type,
-                                                    "fp_input",
-                                                    ir_var_shader_in);
-         ir->data.location = i;
-
          this->current_annotation = ralloc_asprintf(ctx, "interpolate input %d",
                                                     i);
 
          switch (i) {
          case VARYING_SLOT_POS:
-            ir->data.pixel_center_integer = fp->PixelCenterInteger;
-            ir->data.origin_upper_left = fp->OriginUpperLeft;
-            fp_input_regs[i] = *emit_fragcoord_interpolation(ir);
+            {
+               assert(stage == MESA_SHADER_FRAGMENT);
+               gl_fragment_program *fp = (gl_fragment_program*) prog;
+               fp_input_regs[i] =
+                  *emit_fragcoord_interpolation(fp->PixelCenterInteger,
+                                                fp->OriginUpperLeft);
+            }
             break;
          case VARYING_SLOT_FACE:
-            fp_input_regs[i] = *emit_frontfacing_interpolation(ir);
+            fp_input_regs[i] = *emit_frontfacing_interpolation();
             break;
          default:
-            fp_input_regs[i] = *emit_general_interpolation(ir);
+            fp_input_regs[i] = vgrf(glsl_type::vec4_type);
+            emit_general_interpolation(fp_input_regs[i], "fp_input",
+                                       glsl_type::vec4_type,
+                                       INTERP_QUALIFIER_NONE,
+                                       i, false, false);
 
             if (i == VARYING_SLOT_FOGC) {
                emit(MOV(offset(fp_input_regs[i], 1), fs_reg(0.0f)));
@@ -635,6 +611,9 @@ fs_visitor::setup_fp_regs()
 fs_reg
 fs_visitor::get_fp_dst_reg(const prog_dst_register *dst)
 {
+   assert(stage == MESA_SHADER_FRAGMENT);
+   brw_wm_prog_key *key = (brw_wm_prog_key*) this->key;
+
    switch (dst->File) {
    case PROGRAM_TEMPORARY:
       return fp_temp_regs[dst->Index];
@@ -642,17 +621,17 @@ fs_visitor::get_fp_dst_reg(const prog_dst_register *dst)
    case PROGRAM_OUTPUT:
       if (dst->Index == FRAG_RESULT_DEPTH) {
          if (frag_depth.file == BAD_FILE)
-            frag_depth = fs_reg(this, glsl_type::vec4_type);
+            frag_depth = vgrf(glsl_type::vec4_type);
          return frag_depth;
       } else if (dst->Index == FRAG_RESULT_COLOR) {
          if (outputs[0].file == BAD_FILE) {
-            outputs[0] = fs_reg(this, glsl_type::vec4_type);
+            outputs[0] = vgrf(glsl_type::vec4_type);
             output_components[0] = 4;
 
             /* Tell emit_fb_writes() to smear fragment.color across all the
              * color attachments.
              */
-            for (int i = 1; i < c->key.nr_color_regions; i++) {
+            for (int i = 1; i < key->nr_color_regions; i++) {
                outputs[i] = outputs[0];
                output_components[i] = output_components[0];
             }
@@ -661,7 +640,7 @@ fs_visitor::get_fp_dst_reg(const prog_dst_register *dst)
       } else {
          int output_index = dst->Index - FRAG_RESULT_DATA0;
          if (outputs[output_index].file == BAD_FILE) {
-            outputs[output_index] = fs_reg(this, glsl_type::vec4_type);
+            outputs[output_index] = vgrf(glsl_type::vec4_type);
          }
          output_components[output_index] = 4;
          return outputs[output_index];
@@ -673,7 +652,7 @@ fs_visitor::get_fp_dst_reg(const prog_dst_register *dst)
    default:
       _mesa_problem(ctx, "bad dst register file: %s\n",
                     _mesa_register_file_name((gl_register_file)dst->File));
-      return fs_reg(this, glsl_type::vec4_type);
+      return vgrf(glsl_type::vec4_type);
    }
 }
 
@@ -706,7 +685,7 @@ fs_visitor::get_fp_src_reg(const prog_src_register *src)
        */
       switch (plist->Parameters[src->Index].Type) {
       case PROGRAM_CONSTANT: {
-         result = fs_reg(this, glsl_type::vec4_type);
+         result = vgrf(glsl_type::vec4_type);
 
          for (int i = 0; i < 4; i++) {
             emit(MOV(offset(result, i),
@@ -723,19 +702,19 @@ fs_visitor::get_fp_src_reg(const prog_src_register *src)
       default:
          _mesa_problem(ctx, "bad uniform src register file: %s\n",
                        _mesa_register_file_name((gl_register_file)src->File));
-         return fs_reg(this, glsl_type::vec4_type);
+         return vgrf(glsl_type::vec4_type);
       }
       break;
 
    default:
       _mesa_problem(ctx, "bad src register file: %s\n",
                     _mesa_register_file_name((gl_register_file)src->File));
-      return fs_reg(this, glsl_type::vec4_type);
+      return vgrf(glsl_type::vec4_type);
    }
 
    if (src->Swizzle != SWIZZLE_NOOP || src->Negate) {
       fs_reg unswizzled = result;
-      result = fs_reg(this, glsl_type::vec4_type);
+      result = vgrf(glsl_type::vec4_type);
       for (int i = 0; i < 4; i++) {
          bool negate = src->Negate & (1 << i);
          /* The ZERO, ONE, and Negate options are only used for OPCODE_SWZ,