i965/vec4: Make with_writemask() non-static.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_fs_emit.cpp
index bc1fef16b018f4d18d5366ae69796910ed8f6a1b..bfb3d331b0a7e962995f08d07218a59dca0c4160 100644 (file)
@@ -35,7 +35,6 @@ extern "C" {
 
 #include "brw_fs.h"
 #include "brw_cfg.h"
-#include "glsl/ir_print_visitor.h"
 
 fs_generator::fs_generator(struct brw_context *brw,
                            struct brw_wm_compile *c,
@@ -45,8 +44,7 @@ fs_generator::fs_generator(struct brw_context *brw,
 
    : brw(brw), c(c), prog(prog), fp(fp), dual_source_output(dual_source_output)
 {
-   intel = &brw->intel;
-   ctx = &intel->ctx;
+   ctx = &brw->ctx;
 
    shader = prog ? prog->_LinkedShaders[MESA_SHADER_FRAGMENT] : NULL;
 
@@ -60,10 +58,19 @@ fs_generator::~fs_generator()
 {
 }
 
+void
+fs_generator::mark_surface_used(unsigned surf_index)
+{
+   assert(surf_index < BRW_MAX_WM_SURFACES);
+
+   c->prog_data.binding_table_size =
+      MAX2(c->prog_data.binding_table_size, surf_index + 1);
+}
+
 void
 fs_generator::patch_discard_jumps_to_fb_writes()
 {
-   if (intel->gen < 6 || this->discard_halt_patches.is_empty())
+   if (brw->gen < 6 || this->discard_halt_patches.is_empty())
       return;
 
    /* There is a somewhat strange undocumented requirement of using
@@ -112,7 +119,7 @@ fs_generator::generate_fb_write(fs_inst *inst)
    if (fp->UsesKill) {
       struct brw_reg pixel_mask;
 
-      if (intel->gen >= 6)
+      if (brw->gen >= 6)
          pixel_mask = retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UW);
       else
          pixel_mask = retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UW);
@@ -121,16 +128,14 @@ fs_generator::generate_fb_write(fs_inst *inst)
    }
 
    if (inst->header_present) {
-      if (intel->gen >= 6) {
+      if (brw->gen >= 6) {
         brw_set_compression_control(p, BRW_COMPRESSION_COMPRESSED);
         brw_MOV(p,
                 retype(brw_message_reg(inst->base_mrf), BRW_REGISTER_TYPE_UD),
                 retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UD));
         brw_set_compression_control(p, BRW_COMPRESSION_NONE);
 
-         if (inst->target > 0 &&
-            c->key.nr_color_regions > 1 &&
-            c->key.sample_alpha_to_coverage) {
+         if (inst->target > 0 && c->key.replicate_alpha) {
             /* Set "Source0 Alpha Present to RenderTarget" bit in message
              * header.
              */
@@ -174,11 +179,13 @@ fs_generator::generate_fb_write(fs_inst *inst)
                inst->base_mrf,
                implied_header,
                msg_control,
-               inst->target,
+               SURF_INDEX_DRAW(inst->target),
                inst->mlen,
                0,
                eot,
                inst->header_present);
+
+   mark_surface_used(SURF_INDEX_DRAW(inst->target));
 }
 
 /* Computes the integer pixel x,y values from the origin.
@@ -225,7 +232,7 @@ fs_generator::generate_linterp(fs_inst *inst,
 
    if (brw->has_pln &&
        delta_y.nr == delta_x.nr + 1 &&
-       (intel->gen >= 6 || (delta_x.nr & 1) == 0)) {
+       (brw->gen >= 6 || (delta_x.nr & 1) == 0)) {
       brw_PLN(p, dst, interp, delta_x);
    } else {
       brw_LINE(p, brw_null_reg(), interp, delta_x);
@@ -331,6 +338,29 @@ fs_generator::generate_math_gen4(fs_inst *inst,
    }
 }
 
+void
+fs_generator::generate_math_g45(fs_inst *inst,
+                                struct brw_reg dst,
+                                struct brw_reg src)
+{
+   if (inst->opcode == SHADER_OPCODE_POW ||
+       inst->opcode == SHADER_OPCODE_INT_QUOTIENT ||
+       inst->opcode == SHADER_OPCODE_INT_REMAINDER) {
+      generate_math_gen4(inst, dst, src);
+      return;
+   }
+
+   int op = brw_math_function(inst->opcode);
+
+   assert(inst->mlen >= 1);
+
+   brw_math(p, dst,
+            op,
+            inst->base_mrf, src,
+            BRW_MATH_DATA_VECTOR,
+            BRW_MATH_PRECISION_FULL);
+}
+
 void
 fs_generator::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src)
 {
@@ -354,7 +384,7 @@ fs_generator::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src
    if (dispatch_width == 16)
       simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD16;
 
-   if (intel->gen >= 5) {
+   if (brw->gen >= 5) {
       switch (inst->opcode) {
       case SHADER_OPCODE_TEX:
         if (inst->shadow_compare) {
@@ -383,7 +413,7 @@ fs_generator::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src
       case SHADER_OPCODE_TXD:
          if (inst->shadow_compare) {
             /* Gen7.5+.  Otherwise, lowered by brw_lower_texture_gradients(). */
-            assert(intel->is_haswell);
+            assert(brw->is_haswell);
             msg_type = HSW_SAMPLER_MESSAGE_SAMPLE_DERIV_COMPARE;
          } else {
             msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_DERIVS;
@@ -393,7 +423,7 @@ fs_generator::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src
         msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_LD;
         break;
       case SHADER_OPCODE_TXF_MS:
-         if (intel->gen >= 7)
+         if (brw->gen >= 7)
             msg_type = GEN7_SAMPLER_MESSAGE_SAMPLE_LD2DMS;
          else
             msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_LD;
@@ -500,6 +530,8 @@ fs_generator::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src
              inst->header_present,
              simd_mode,
              return_format);
+
+   mark_surface_used(SURF_INDEX_TEXTURE(inst->sampler));
 }
 
 
@@ -576,7 +608,7 @@ fs_generator::generate_ddy(fs_inst *inst, struct brw_reg dst, struct brw_reg src
 void
 fs_generator::generate_discard_jump(fs_inst *inst)
 {
-   assert(intel->gen >= 6);
+   assert(brw->gen >= 6);
 
    /* This HALT will be patched up at FB write time to point UIP at the end of
     * the program, and at brw_uip_jip() JIP will be set to the end of the
@@ -629,6 +661,8 @@ fs_generator::generate_uniform_pull_constant_load(fs_inst *inst,
 
    brw_oword_block_read(p, dst, brw_message_reg(inst->base_mrf),
                        read_offset, surf_index);
+
+   mark_surface_used(surf_index);
 }
 
 void
@@ -669,52 +703,75 @@ fs_generator::generate_uniform_pull_constant_load_gen7(fs_inst *inst,
                            false, /* no header */
                            BRW_SAMPLER_SIMD_MODE_SIMD4X2,
                            0);
+
+   mark_surface_used(surf_index);
 }
 
 void
 fs_generator::generate_varying_pull_constant_load(fs_inst *inst,
                                                   struct brw_reg dst,
-                                                  struct brw_reg index)
+                                                  struct brw_reg index,
+                                                  struct brw_reg offset)
 {
-   assert(intel->gen < 7); /* Should use the gen7 variant. */
+   assert(brw->gen < 7); /* Should use the gen7 variant. */
    assert(inst->header_present);
+   assert(inst->mlen);
 
    assert(index.file == BRW_IMMEDIATE_VALUE &&
          index.type == BRW_REGISTER_TYPE_UD);
    uint32_t surf_index = index.dw1.ud;
 
-   uint32_t msg_type, msg_control, rlen;
-   if (intel->gen >= 6)
-      msg_type = GEN6_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ;
-   else if (intel->gen == 5 || intel->is_g4x)
-      msg_type = G45_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ;
-   else
-      msg_type = BRW_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ;
-
+   uint32_t simd_mode, rlen, msg_type;
    if (dispatch_width == 16) {
-      msg_control = BRW_DATAPORT_DWORD_SCATTERED_BLOCK_16DWORDS;
-      rlen = 2;
+      simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD16;
+      rlen = 8;
    } else {
-      msg_control = BRW_DATAPORT_DWORD_SCATTERED_BLOCK_8DWORDS;
-      rlen = 1;
+      simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD8;
+      rlen = 4;
    }
 
+   if (brw->gen >= 5)
+      msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_LD;
+   else {
+      /* We always use the SIMD16 message so that we only have to load U, and
+       * not V or R.
+       */
+      msg_type = BRW_SAMPLER_MESSAGE_SIMD16_LD;
+      assert(inst->mlen == 3);
+      assert(inst->regs_written == 8);
+      rlen = 8;
+      simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD16;
+   }
+
+   struct brw_reg offset_mrf = retype(brw_message_reg(inst->base_mrf + 1),
+                                      BRW_REGISTER_TYPE_D);
+   brw_MOV(p, offset_mrf, offset);
+
    struct brw_reg header = brw_vec8_grf(0, 0);
    gen6_resolve_implied_move(p, &header, inst->base_mrf);
 
    struct brw_instruction *send = brw_next_insn(p, BRW_OPCODE_SEND);
+   send->header.compression_control = BRW_COMPRESSION_NONE;
    brw_set_dest(p, send, dst);
    brw_set_src0(p, send, header);
-   if (intel->gen < 6)
+   if (brw->gen < 6)
       send->header.destreg__conditionalmod = inst->base_mrf;
-   brw_set_dp_read_message(p, send,
+
+   /* Our surface is set up as floats, regardless of what actual data is
+    * stored in it.
+    */
+   uint32_t return_format = BRW_SAMPLER_RETURN_FORMAT_FLOAT32;
+   brw_set_sampler_message(p, send,
                            surf_index,
-                           msg_control,
+                           0, /* sampler (unused) */
                            msg_type,
-                           BRW_DATAPORT_READ_TARGET_DATA_CACHE,
+                           rlen,
                            inst->mlen,
                            inst->header_present,
-                           rlen);
+                           simd_mode,
+                           return_format);
+
+   mark_surface_used(surf_index);
 }
 
 void
@@ -723,7 +780,7 @@ fs_generator::generate_varying_pull_constant_load_gen7(fs_inst *inst,
                                                        struct brw_reg index,
                                                        struct brw_reg offset)
 {
-   assert(intel->gen >= 7);
+   assert(brw->gen >= 7);
    /* Varying-offset pull constant loads are treated as a normal expression on
     * gen7, so the fact that it's a send message is hidden at the IR level.
     */
@@ -757,6 +814,8 @@ fs_generator::generate_varying_pull_constant_load_gen7(fs_inst *inst,
                            false, /* no header */
                            simd_mode,
                            0);
+
+   mark_surface_used(surf_index);
 }
 
 /**
@@ -771,7 +830,7 @@ fs_generator::generate_mov_dispatch_to_flags(fs_inst *inst)
    struct brw_reg flags = brw_flag_reg(0, inst->flag_subreg);
    struct brw_reg dispatch_mask;
 
-   if (intel->gen >= 6)
+   if (brw->gen >= 6)
       dispatch_mask = retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UW);
    else
       dispatch_mask = retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UW);
@@ -835,7 +894,7 @@ brw_reg_from_fs_reg(fs_reg *reg)
         break;
       }
       break;
-   case FIXED_HW_REG:
+   case HW_REG:
       brw_reg = reg->fixed_hw_reg;
       break;
    case BAD_FILE:
@@ -907,7 +966,7 @@ fs_generator::generate_pack_half_2x16_split(fs_inst *inst,
                                             struct brw_reg x,
                                             struct brw_reg y)
 {
-   assert(intel->gen >= 7);
+   assert(brw->gen >= 7);
    assert(dst.type == BRW_REGISTER_TYPE_UD);
    assert(x.type == BRW_REGISTER_TYPE_F);
    assert(y.type == BRW_REGISTER_TYPE_F);
@@ -945,7 +1004,7 @@ fs_generator::generate_unpack_half_2x16_split(fs_inst *inst,
                                               struct brw_reg dst,
                                               struct brw_reg src)
 {
-   assert(intel->gen >= 7);
+   assert(brw->gen >= 7);
    assert(dst.type == BRW_REGISTER_TYPE_F);
    assert(src.type == BRW_REGISTER_TYPE_UD);
 
@@ -975,7 +1034,7 @@ fs_generator::generate_shader_time_add(fs_inst *inst,
                                        struct brw_reg offset,
                                        struct brw_reg value)
 {
-   assert(intel->gen >= 7);
+   assert(brw->gen >= 7);
    brw_push_insn_state(p);
    brw_set_mask_control(p, true);
 
@@ -1002,6 +1061,8 @@ fs_generator::generate_shader_time_add(fs_inst *inst,
    brw_MOV(p, payload_value, value);
    brw_shader_time_add(p, payload, SURF_INDEX_WM_SHADER_TIME);
    brw_pop_insn_state(p);
+
+   mark_surface_used(SURF_INDEX_WM_SHADER_TIME);
 }
 
 void
@@ -1190,11 +1251,59 @@ fs_generator::generate_code(exec_list *instructions)
       case BRW_OPCODE_SEL:
         brw_SEL(p, dst, src[0], src[1]);
         break;
+      case BRW_OPCODE_BFREV:
+         /* BFREV only supports UD type for src and dst. */
+         brw_BFREV(p, retype(dst, BRW_REGISTER_TYPE_UD),
+                      retype(src[0], BRW_REGISTER_TYPE_UD));
+         break;
+      case BRW_OPCODE_FBH:
+         /* FBH only supports UD type for dst. */
+         brw_FBH(p, retype(dst, BRW_REGISTER_TYPE_UD), src[0]);
+         break;
+      case BRW_OPCODE_FBL:
+         /* FBL only supports UD type for dst. */
+         brw_FBL(p, retype(dst, BRW_REGISTER_TYPE_UD), src[0]);
+         break;
+      case BRW_OPCODE_CBIT:
+         /* CBIT only supports UD type for dst. */
+         brw_CBIT(p, retype(dst, BRW_REGISTER_TYPE_UD), src[0]);
+         break;
+
+      case BRW_OPCODE_BFE:
+         brw_set_access_mode(p, BRW_ALIGN_16);
+         if (dispatch_width == 16) {
+            brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+            brw_BFE(p, dst, src[0], src[1], src[2]);
+            brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF);
+            brw_BFE(p, sechalf(dst), sechalf(src[0]), sechalf(src[1]), sechalf(src[2]));
+            brw_set_compression_control(p, BRW_COMPRESSION_COMPRESSED);
+         } else {
+            brw_BFE(p, dst, src[0], src[1], src[2]);
+         }
+         brw_set_access_mode(p, BRW_ALIGN_1);
+         break;
+
+      case BRW_OPCODE_BFI1:
+         brw_BFI1(p, dst, src[0], src[1]);
+         break;
+      case BRW_OPCODE_BFI2:
+         brw_set_access_mode(p, BRW_ALIGN_16);
+         if (dispatch_width == 16) {
+            brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+            brw_BFI2(p, dst, src[0], src[1], src[2]);
+            brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF);
+            brw_BFI2(p, sechalf(dst), sechalf(src[0]), sechalf(src[1]), sechalf(src[2]));
+            brw_set_compression_control(p, BRW_COMPRESSION_COMPRESSED);
+         } else {
+            brw_BFI2(p, dst, src[0], src[1], src[2]);
+         }
+         brw_set_access_mode(p, BRW_ALIGN_1);
+         break;
 
       case BRW_OPCODE_IF:
         if (inst->src[0].file != BAD_FILE) {
            /* The instruction has an embedded compare (only allowed on gen6) */
-           assert(intel->gen == 6);
+           assert(brw->gen == 6);
            gen6_IF(p, inst->conditional_mod, src[0], src[1]);
         } else {
            brw_IF(p, dispatch_width == 16 ? BRW_EXECUTE_16 : BRW_EXECUTE_8);
@@ -1218,7 +1327,7 @@ fs_generator::generate_code(exec_list *instructions)
         break;
       case BRW_OPCODE_CONTINUE:
         /* FINISHME: We need to write the loop instruction support still. */
-        if (intel->gen >= 6)
+        if (brw->gen >= 6)
            gen6_CONT(p);
         else
            brw_CONT(p);
@@ -1236,10 +1345,12 @@ fs_generator::generate_code(exec_list *instructions)
       case SHADER_OPCODE_LOG2:
       case SHADER_OPCODE_SIN:
       case SHADER_OPCODE_COS:
-        if (intel->gen >= 7) {
+        if (brw->gen >= 7) {
            generate_math1_gen7(inst, dst, src[0]);
-        } else if (intel->gen == 6) {
+        } else if (brw->gen == 6) {
            generate_math1_gen6(inst, dst, src[0]);
+        } else if (brw->gen == 5 || brw->is_g4x) {
+           generate_math_g45(inst, dst, src[0]);
         } else {
            generate_math_gen4(inst, dst, src[0]);
         }
@@ -1247,9 +1358,9 @@ fs_generator::generate_code(exec_list *instructions)
       case SHADER_OPCODE_INT_QUOTIENT:
       case SHADER_OPCODE_INT_REMAINDER:
       case SHADER_OPCODE_POW:
-        if (intel->gen >= 7) {
+        if (brw->gen >= 7) {
            generate_math2_gen7(inst, dst, src[0], src[1]);
-        } else if (intel->gen == 6) {
+        } else if (brw->gen == 6) {
            generate_math2_gen6(inst, dst, src[0], src[1]);
         } else {
            generate_math_gen4(inst, dst, src[0]);
@@ -1305,7 +1416,7 @@ fs_generator::generate_code(exec_list *instructions)
         break;
 
       case FS_OPCODE_VARYING_PULL_CONSTANT_LOAD:
-        generate_varying_pull_constant_load(inst, dst, src[0]);
+        generate_varying_pull_constant_load(inst, dst, src[0], src[1]);
         break;
 
       case FS_OPCODE_VARYING_PULL_CONSTANT_LOAD_GEN7: