i965/vec4: Only zero out unused message components when there are any.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_vec4.cpp
index b6d454f41750290ffce13bd7030d4d3ec566c2e7..2c1f54158b73e229bbc2b899af3eed2c5ba2fb31 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "brw_vec4.h"
 #include "brw_cfg.h"
-#include "glsl/ir_print_visitor.h"
+#include "brw_vs.h"
 
 extern "C" {
 #include "main/macros.h"
@@ -141,17 +141,6 @@ src_reg::src_reg(dst_reg reg)
                                 swizzles[2], swizzles[3]);
 }
 
-bool
-vec4_instruction::is_tex()
-{
-   return (opcode == SHADER_OPCODE_TEX ||
-          opcode == SHADER_OPCODE_TXD ||
-          opcode == SHADER_OPCODE_TXF ||
-          opcode == SHADER_OPCODE_TXF_MS ||
-          opcode == SHADER_OPCODE_TXL ||
-          opcode == SHADER_OPCODE_TXS);
-}
-
 void
 dst_reg::init()
 {
@@ -212,21 +201,6 @@ dst_reg::dst_reg(src_reg reg)
    this->fixed_hw_reg = reg.fixed_hw_reg;
 }
 
-bool
-vec4_instruction::is_math()
-{
-   return (opcode == SHADER_OPCODE_RCP ||
-          opcode == SHADER_OPCODE_RSQ ||
-          opcode == SHADER_OPCODE_SQRT ||
-          opcode == SHADER_OPCODE_EXP2 ||
-          opcode == SHADER_OPCODE_LOG2 ||
-          opcode == SHADER_OPCODE_SIN ||
-          opcode == SHADER_OPCODE_COS ||
-          opcode == SHADER_OPCODE_INT_QUOTIENT ||
-          opcode == SHADER_OPCODE_INT_REMAINDER ||
-          opcode == SHADER_OPCODE_POW);
-}
-
 bool
 vec4_instruction::is_send_from_grf()
 {
@@ -242,7 +216,7 @@ vec4_instruction::is_send_from_grf()
 bool
 vec4_visitor::can_do_source_mods(vec4_instruction *inst)
 {
-   if (intel->gen == 6 && inst->is_math())
+   if (brw->gen == 6 && inst->is_math())
       return false;
 
    if (inst->is_send_from_grf())
@@ -273,6 +247,8 @@ vec4_visitor::implied_mrf_writes(vec4_instruction *inst)
    case SHADER_OPCODE_SIN:
    case SHADER_OPCODE_COS:
       return 1;
+   case SHADER_OPCODE_INT_QUOTIENT:
+   case SHADER_OPCODE_INT_REMAINDER:
    case SHADER_OPCODE_POW:
       return 2;
    case VS_OPCODE_URB_WRITE:
@@ -283,8 +259,18 @@ vec4_visitor::implied_mrf_writes(vec4_instruction *inst)
       return 2;
    case VS_OPCODE_SCRATCH_WRITE:
       return 3;
+   case GS_OPCODE_URB_WRITE:
+   case GS_OPCODE_THREAD_END:
+      return 0;
    case SHADER_OPCODE_SHADER_TIME_ADD:
       return 0;
+   case SHADER_OPCODE_TEX:
+   case SHADER_OPCODE_TXL:
+   case SHADER_OPCODE_TXD:
+   case SHADER_OPCODE_TXF:
+   case SHADER_OPCODE_TXF_MS:
+   case SHADER_OPCODE_TXS:
+      return inst->header_present ? 1 : 0;
    default:
       assert(!"not reached");
       return inst->mlen;
@@ -324,9 +310,12 @@ vec4_visitor::dead_code_eliminate()
    foreach_list_safe(node, &this->instructions) {
       vec4_instruction *inst = (vec4_instruction *)node;
 
-      if (inst->dst.file == GRF && this->virtual_grf_use[inst->dst.reg] <= pc) {
-        inst->remove();
-        progress = true;
+      if (inst->dst.file == GRF) {
+         assert(this->virtual_grf_end[inst->dst.reg] >= pc);
+         if (this->virtual_grf_end[inst->dst.reg] == pc) {
+            inst->remove();
+            progress = true;
+         }
       }
 
       pc++;
@@ -806,7 +795,6 @@ vec4_instruction::reswizzle_dst(int dst_writemask, int swizzle)
       break;
    default:
       for (int c = 0; c < 4; c++) {
-         int bit = 1 << BRW_GET_SWZ(swizzle, c);
          /* Skip components of the swizzle not used by the dst. */
          if (!(dst_writemask & (1 << c)))
             continue;
@@ -814,7 +802,7 @@ vec4_instruction::reswizzle_dst(int dst_writemask, int swizzle)
          /* We don't do the reswizzling yet, so just sanity check that we
           * don't have to.
           */
-         assert(bit == (1 << c));
+         assert((1 << BRW_GET_SWZ(swizzle, c)) == (1 << c));
       }
       break;
    }
@@ -852,7 +840,7 @@ vec4_visitor::opt_register_coalesce()
       /* Can't coalesce this GRF if someone else was going to
        * read it later.
        */
-      if (this->virtual_grf_use[inst->src[0].reg] > ip)
+      if (this->virtual_grf_end[inst->src[0].reg] > ip)
         continue;
 
       /* We need to check interference with the final destination between this
@@ -894,7 +882,7 @@ vec4_visitor::opt_register_coalesce()
                if (scan_inst->mlen)
                   break;
 
-               if (intel->gen == 6) {
+               if (brw->gen == 6) {
                   /* gen6 math instructions must have the destination be
                    * GRF, so no compute-to-MRF for them.
                    */
@@ -1046,10 +1034,14 @@ vec4_visitor::split_virtual_grfs()
       vec4_instruction *inst = (vec4_instruction *)node;
 
       /* If there's a SEND message loading from a GRF on gen7+, it needs to be
-       * contiguous.  Assume that the GRF for the SEND is always in src[0].
+       * contiguous.
        */
       if (inst->is_send_from_grf()) {
-         split_grf[inst->src[0].reg] = false;
+         for (int i = 0; i < 3; i++) {
+            if (inst->src[i].file == GRF) {
+               split_grf[inst->src[i].reg] = false;
+            }
+         }
       }
    }
 
@@ -1091,8 +1083,10 @@ vec4_visitor::split_virtual_grfs()
 }
 
 void
-vec4_visitor::dump_instruction(vec4_instruction *inst)
+vec4_visitor::dump_instruction(backend_instruction *be_inst)
 {
+   vec4_instruction *inst = (vec4_instruction *)be_inst;
+
    printf("%s ", brw_instruction_name(inst->opcode));
 
    switch (inst->dst.file) {
@@ -1173,17 +1167,6 @@ vec4_visitor::dump_instruction(vec4_instruction *inst)
    printf("\n");
 }
 
-void
-vec4_visitor::dump_instructions()
-{
-   int ip = 0;
-   foreach_list_safe(node, &this->instructions) {
-      vec4_instruction *inst = (vec4_instruction *)node;
-      printf("%d: ", ip++);
-      dump_instruction(inst);
-   }
-}
-
 /**
  * Replace each register of type ATTR in this->instructions with a reference
  * to a fixed HW register.
@@ -1198,6 +1181,11 @@ vec4_visitor::lower_attributes_to_hw_regs(const int *attribute_map)
       if (inst->dst.file == ATTR) {
         int grf = attribute_map[inst->dst.reg + inst->dst.reg_offset];
 
+         /* All attributes used in the shader need to have been assigned a
+          * hardware register by the caller
+          */
+         assert(grf != 0);
+
         struct brw_reg reg = brw_vec8_grf(grf, 0);
         reg.type = inst->dst.type;
         reg.dw1.bits.writemask = inst->dst.writemask;
@@ -1212,6 +1200,11 @@ vec4_visitor::lower_attributes_to_hw_regs(const int *attribute_map)
 
         int grf = attribute_map[inst->src[i].reg + inst->src[i].reg_offset];
 
+         /* All attributes used in the shader need to have been assigned a
+          * hardware register by the caller
+          */
+         assert(grf != 0);
+
         struct brw_reg reg = brw_vec8_grf(grf, 0);
         reg.dw1.bits.swizzle = inst->src[i].swizzle;
          reg.type = inst->src[i].type;
@@ -1231,6 +1224,7 @@ vec4_vs_visitor::setup_attributes(int payload_reg)
 {
    int nr_attributes;
    int attribute_map[VERT_ATTRIB_MAX + 1];
+   memset(attribute_map, 0, sizeof(attribute_map));
 
    nr_attributes = 0;
    for (int i = 0; i < VERT_ATTRIB_MAX; i++) {
@@ -1262,7 +1256,7 @@ vec4_vs_visitor::setup_attributes(int payload_reg)
    unsigned vue_entries =
       MAX2(nr_attributes, prog_data->vue_map.num_slots);
 
-   if (intel->gen == 6)
+   if (brw->gen == 6)
       prog_data->urb_entry_size = ALIGN(vue_entries, 8) / 8;
    else
       prog_data->urb_entry_size = ALIGN(vue_entries, 4) / 4;
@@ -1273,12 +1267,15 @@ vec4_vs_visitor::setup_attributes(int payload_reg)
 int
 vec4_visitor::setup_uniforms(int reg)
 {
+   prog_data->dispatch_grf_start_reg = reg;
+
    /* The pre-gen6 VS requires that some push constants get loaded no
     * matter what, or the GPU would hang.
     */
-   if (intel->gen < 6 && this->uniforms == 0) {
+   if (brw->gen < 6 && this->uniforms == 0) {
       this->uniform_vector_size[this->uniforms] = 1;
 
+      prog_data->param = reralloc(NULL, prog_data->param, const float *, 4);
       for (unsigned int i = 0; i < 4; i++) {
         unsigned int slot = this->uniforms * 4 + i;
         static float zero = 0.0;
@@ -1293,13 +1290,13 @@ vec4_visitor::setup_uniforms(int reg)
 
    prog_data->nr_params = this->uniforms * 4;
 
-   prog_data->curb_read_length = reg - 1;
+   prog_data->curb_read_length = reg - prog_data->dispatch_grf_start_reg;
 
    return reg;
 }
 
 void
-vec4_visitor::setup_payload(void)
+vec4_vs_visitor::setup_payload(void)
 {
    int reg = 0;
 
@@ -1319,7 +1316,7 @@ vec4_visitor::setup_payload(void)
 src_reg
 vec4_visitor::get_timestamp()
 {
-   assert(intel->gen >= 7);
+   assert(brw->gen >= 7);
 
    src_reg ts = src_reg(brw_reg(BRW_ARCHITECTURE_REGISTER_FILE,
                                 BRW_ARF_TIMESTAMP,
@@ -1487,6 +1484,8 @@ vec4_visitor::run()
          break;
    }
 
+   opt_schedule_instructions();
+
    opt_set_dependency_control();
 
    /* If any state parameters were appended, then ParameterValues could have
@@ -1516,13 +1515,12 @@ brw_vs_emit(struct brw_context *brw,
             void *mem_ctx,
             unsigned *final_assembly_size)
 {
-   struct intel_context *intel = &brw->intel;
    bool start_busy = false;
    float start_time = 0;
 
-   if (unlikely(intel->perf_debug)) {
-      start_busy = (intel->batch.last_bo &&
-                    drm_intel_bo_busy(intel->batch.last_bo));
+   if (unlikely(brw->perf_debug)) {
+      start_busy = (brw->batch.last_bo &&
+                    drm_intel_bo_busy(brw->batch.last_bo));
       start_time = get_time();
    }
 
@@ -1531,7 +1529,7 @@ brw_vs_emit(struct brw_context *brw,
       shader = (brw_shader *) prog->_LinkedShaders[MESA_SHADER_VERTEX];
 
    if (unlikely(INTEL_DEBUG & DEBUG_VS)) {
-      if (shader) {
+      if (prog) {
          printf("GLSL IR for native vertex shader %d:\n", prog->Name);
          _mesa_print_ir(shader->ir, NULL);
          printf("\n\n");
@@ -1544,21 +1542,27 @@ brw_vs_emit(struct brw_context *brw,
 
    vec4_vs_visitor v(brw, c, prog_data, prog, shader, mem_ctx);
    if (!v.run()) {
-      prog->LinkStatus = false;
-      ralloc_strcat(&prog->InfoLog, v.fail_msg);
+      if (prog) {
+         prog->LinkStatus = false;
+         ralloc_strcat(&prog->InfoLog, v.fail_msg);
+      }
+
+      _mesa_problem(NULL, "Failed to compile vertex shader: %s\n",
+                    v.fail_msg);
+
       return NULL;
    }
 
-   vec4_generator g(brw, prog, &c->vp->program.Base, mem_ctx,
+   vec4_generator g(brw, prog, &c->vp->program.Base, &prog_data->base, mem_ctx,
                     INTEL_DEBUG & DEBUG_VS);
    const unsigned *generated =g.generate_assembly(&v.instructions,
                                                   final_assembly_size);
 
-   if (unlikely(intel->perf_debug) && shader) {
+   if (unlikely(brw->perf_debug) && shader) {
       if (shader->compiled_once) {
          brw_vs_debug_recompile(brw, prog, &c->key);
       }
-      if (start_busy && !drm_intel_bo_busy(intel->batch.last_bo)) {
+      if (start_busy && !drm_intel_bo_busy(brw->batch.last_bo)) {
          perf_debug("VS compile took %.03f ms and stalled the GPU\n",
                     (get_time() - start_time) * 1000);
       }
@@ -1568,4 +1572,31 @@ brw_vs_emit(struct brw_context *brw,
    return generated;
 }
 
+
+bool
+brw_vec4_prog_data_compare(const struct brw_vec4_prog_data *a,
+                           const struct brw_vec4_prog_data *b)
+{
+   /* Compare all the struct up to the pointers. */
+   if (memcmp(a, b, offsetof(struct brw_vec4_prog_data, param)))
+      return false;
+
+   if (memcmp(a->param, b->param, a->nr_params * sizeof(void *)))
+      return false;
+
+   if (memcmp(a->pull_param, b->pull_param, a->nr_pull_params * sizeof(void *)))
+      return false;
+
+   return true;
+}
+
+
+void
+brw_vec4_prog_data_free(const struct brw_vec4_prog_data *prog_data)
+{
+   ralloc_free((void *)prog_data->param);
+   ralloc_free((void *)prog_data->pull_param);
+}
+
+
 } /* extern "C" */