i965: Refactor SIMD16-to-2xSIMD8 checks.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_fs_generator.cpp
index 3475b31338efd8ca5fd910a79cf6e0a689e8d7fa..6eebee16ed42e7e0fa3b61a8e2aadc8affe5fe86 100644 (file)
  * native instructions.
  */
 
-extern "C" {
 #include "main/macros.h"
 #include "brw_context.h"
 #include "brw_eu.h"
-} /* extern "C" */
-
 #include "brw_fs.h"
 #include "brw_cfg.h"
 
@@ -129,13 +126,15 @@ fs_generator::fs_generator(struct brw_context *brw,
                            const void *key,
                            struct brw_stage_prog_data *prog_data,
                            struct gl_program *prog,
+                           unsigned promoted_constants,
                            bool runtime_check_aads_emit,
                            const char *stage_abbrev)
 
    : brw(brw), key(key),
      prog_data(prog_data),
-     prog(prog), runtime_check_aads_emit(runtime_check_aads_emit),
-     debug_flag(false), stage_abbrev(stage_abbrev), mem_ctx(mem_ctx)
+     prog(prog), promoted_constants(promoted_constants),
+     runtime_check_aads_emit(runtime_check_aads_emit), debug_flag(false),
+     stage_abbrev(stage_abbrev), mem_ctx(mem_ctx)
 {
    ctx = &brw->ctx;
 
@@ -217,9 +216,12 @@ fs_generator::fire_fb_write(fs_inst *inst,
 
    if (inst->opcode == FS_OPCODE_REP_FB_WRITE)
       msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE_REPLICATED;
-   else if (prog_data->dual_src_blend)
-      msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN01;
-   else if (dispatch_width == 16)
+   else if (prog_data->dual_src_blend) {
+      if (dispatch_width == 8 || !inst->eot)
+         msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN01;
+      else
+         msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN23;
+   } else if (dispatch_width == 16)
       msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE;
    else
       msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_SINGLE_SOURCE_SUBSPAN01;
@@ -227,6 +229,10 @@ fs_generator::fire_fb_write(fs_inst *inst,
    uint32_t surf_index =
       prog_data->binding_table.render_target_start + inst->target;
 
+   bool last_render_target = inst->eot ||
+                             (prog_data->dual_src_blend && dispatch_width == 16);
+
+
    brw_fb_WRITE(p,
                 dispatch_width,
                 payload,
@@ -236,6 +242,7 @@ fs_generator::fire_fb_write(fs_inst *inst,
                 nr,
                 0,
                 inst->eot,
+                last_render_target,
                 inst->header_present);
 
    brw_mark_surface_used(&prog_data->base, surf_index);
@@ -373,6 +380,7 @@ fs_generator::generate_blorp_fb_write(fs_inst *inst)
                 inst->mlen,
                 0,
                 true,
+                true,
                 inst->header_present);
 }
 
@@ -1399,27 +1407,6 @@ fs_generator::generate_set_sample_id(fs_inst *inst,
    brw_pop_insn_state(p);
 }
 
-/**
- * Change the register's data type from UD to W, doubling the strides in order
- * to compensate for halving the data type width.
- */
-static struct brw_reg
-ud_reg_to_w(struct brw_reg r)
-{
-   assert(r.type == BRW_REGISTER_TYPE_UD);
-   r.type = BRW_REGISTER_TYPE_W;
-
-   /* The BRW_*_STRIDE enums are defined so that incrementing the field
-    * doubles the real stride.
-    */
-   if (r.hstride != 0)
-      ++r.hstride;
-   if (r.vstride != 0)
-      ++r.vstride;
-
-   return r;
-}
-
 void
 fs_generator::generate_pack_half_2x16_split(fs_inst *inst,
                                             struct brw_reg dst,
@@ -1440,9 +1427,9 @@ fs_generator::generate_pack_half_2x16_split(fs_inst *inst,
     *   (HorzStride) of 2. The 16-bit result is stored in the lower word of
     *   each destination channel and the upper word is not modified.
     */
-   struct brw_reg dst_w = ud_reg_to_w(dst);
+   struct brw_reg dst_w = spread(retype(dst, BRW_REGISTER_TYPE_W), 2);
 
-   /* Give each 32-bit channel of dst the form below , where "." means
+   /* Give each 32-bit channel of dst the form below, where "." means
     * unchanged.
     *   0x....hhhh
     */
@@ -1474,7 +1461,7 @@ fs_generator::generate_unpack_half_2x16_split(fs_inst *inst,
     *   the source data type must be Word (W). The destination type must be
     *   F (Float).
     */
-   struct brw_reg src_w = ud_reg_to_w(src);
+   struct brw_reg src_w = spread(retype(src, BRW_REGISTER_TYPE_W), 2);
 
    /* Each channel of src has the form of unpackHalf2x16's input: 0xhhhhllll.
     * For the Y case, we wish to access only the upper word; therefore
@@ -1566,6 +1553,15 @@ fs_generator::enable_debug(const char *shader_name)
    this->shader_name = shader_name;
 }
 
+/**
+ * Some hardware doesn't support SIMD16 instructions with 3 sources.
+ */
+static bool
+brw_supports_simd16_3src(const struct brw_context *brw)
+{
+   return brw->is_haswell || brw->gen >= 8;
+}
+
 int
 fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
 {
@@ -1578,6 +1574,7 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
       brw_set_default_compression_control(p, BRW_COMPRESSION_COMPRESSED);
 
    int start_offset = p->next_insn_offset;
+   int spill_count = 0, fill_count = 0;
    int loop_count = 0;
 
    struct annotation_info annotation;
@@ -1617,6 +1614,7 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
       case 1:
       case 2:
       case 4:
+         assert(inst->force_writemask_all);
          brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
          break;
       case 8:
@@ -1657,7 +1655,7 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
       case BRW_OPCODE_MAD:
          assert(brw->gen >= 6);
         brw_set_default_access_mode(p, BRW_ALIGN_16);
-         if (dispatch_width == 16 && brw->gen < 8 && !brw->is_haswell) {
+         if (dispatch_width == 16 && !brw_supports_simd16_3src(brw)) {
            brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
             brw_inst *f = brw_MAD(p, firsthalf(dst), firsthalf(src[0]), firsthalf(src[1]), firsthalf(src[2]));
            brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
@@ -1678,7 +1676,7 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
       case BRW_OPCODE_LRP:
          assert(brw->gen >= 6);
         brw_set_default_access_mode(p, BRW_ALIGN_16);
-         if (dispatch_width == 16 && brw->gen < 8 && !brw->is_haswell) {
+         if (dispatch_width == 16 && !brw_supports_simd16_3src(brw)) {
            brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
             brw_inst *f = brw_LRP(p, firsthalf(dst), firsthalf(src[0]), firsthalf(src[1]), firsthalf(src[2]));
            brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
@@ -1815,7 +1813,7 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
       case BRW_OPCODE_BFE:
          assert(brw->gen >= 7);
          brw_set_default_access_mode(p, BRW_ALIGN_16);
-         if (dispatch_width == 16 && brw->gen < 8 && !brw->is_haswell) {
+         if (dispatch_width == 16 && !brw_supports_simd16_3src(brw)) {
             brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
             brw_BFE(p, firsthalf(dst), firsthalf(src[0]), firsthalf(src[1]), firsthalf(src[2]));
             brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
@@ -1855,7 +1853,8 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
           * Otherwise we would be able to emit compressed instructions like we
           * do for the other three-source instructions.
           */
-         if (dispatch_width == 16 && brw->gen < 8) {
+         if (dispatch_width == 16 &&
+             (brw->is_haswell || !brw_supports_simd16_3src(brw))) {
             brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
             brw_BFI2(p, firsthalf(dst), firsthalf(src[0]), firsthalf(src[1]), firsthalf(src[2]));
             brw_set_default_compression_control(p, BRW_COMPRESSION_2NDHALF);
@@ -1973,14 +1972,17 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
 
       case SHADER_OPCODE_GEN4_SCRATCH_WRITE:
         generate_scratch_write(inst, src[0]);
+         spill_count++;
         break;
 
       case SHADER_OPCODE_GEN4_SCRATCH_READ:
         generate_scratch_read(inst, dst);
+         fill_count++;
         break;
 
       case SHADER_OPCODE_GEN7_SCRATCH_READ:
         generate_scratch_read_gen7(inst, dst);
+         fill_count++;
         break;
 
       case SHADER_OPCODE_URB_WRITE_SIMD8:
@@ -2125,10 +2127,10 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
 
    if (unlikely(debug_flag)) {
       fprintf(stderr, "Native code for %s\n"
-              "SIMD%d shader: %d instructions. %d loops. Compacted %d to %d"
+              "SIMD%d shader: %d instructions. %d loops. %d:%d spills:fills. Promoted %u constants. Compacted %d to %d"
               " bytes (%.0f%%)\n",
-              shader_name,
-              dispatch_width, before_size / 16, loop_count, before_size, after_size,
+              shader_name, dispatch_width, before_size / 16, loop_count,
+              spill_count, fill_count, promoted_constants, before_size, after_size,
               100.0f * (before_size - after_size) / before_size);
 
       dump_assembly(p->store, annotation.ann_count, annotation.ann, brw, prog);
@@ -2140,10 +2142,10 @@ fs_generator::generate_code(const cfg_t *cfg, int dispatch_width)
                   MESA_DEBUG_SOURCE_SHADER_COMPILER,
                   MESA_DEBUG_TYPE_OTHER,
                   MESA_DEBUG_SEVERITY_NOTIFICATION,
-                  "%s SIMD%d shader: %d inst, %d loops, "
-                  "compacted %d to %d bytes.\n",
+                  "%s SIMD%d shader: %d inst, %d loops, %d:%d spills:fills, "
+                  "Promoted %u constants, compacted %d to %d bytes.\n",
                   stage_abbrev, dispatch_width, before_size / 16, loop_count,
-                  before_size, after_size);
+                  spill_count, fill_count, promoted_constants, before_size, after_size);
 
    return start_offset;
 }