i965/vec4: split instructions that read 64-bit interleaved attributes
authorIago Toral Quiroga <itoral@igalia.com>
Fri, 1 Jul 2016 07:26:32 +0000 (09:26 +0200)
committerSamuel Iglesias Gonsálvez <siglesias@igalia.com>
Tue, 3 Jan 2017 10:26:51 +0000 (11:26 +0100)
Stages that use interleaved attributes generate regions with a vstride=0
that can hit the gen7 hardware decompression bug.

v2:
- Make static the function and fix indent (Matt)

Reviewed-by: Matt Turner <mattst88@gmail.com>
src/mesa/drivers/dri/i965/brw_vec4.cpp

index 9f6d9a8..dff8a93 100644 (file)
@@ -2034,6 +2034,20 @@ vec4_visitor::convert_to_hw_regs()
    }
 }
 
+static bool
+stage_uses_interleaved_attributes(unsigned stage,
+                                  enum shader_dispatch_mode dispatch_mode)
+{
+   switch (stage) {
+   case MESA_SHADER_TESS_EVAL:
+      return true;
+   case MESA_SHADER_GEOMETRY:
+      return dispatch_mode != DISPATCH_MODE_4X2_DUAL_OBJECT;
+   default:
+      return false;
+   }
+}
+
 /**
  * Get the closest native SIMD width supported by the hardware for instruction
  * \p inst.  The instruction will be left untouched by
@@ -2042,7 +2056,8 @@ vec4_visitor::convert_to_hw_regs()
  */
 static unsigned
 get_lowered_simd_width(const struct gen_device_info *devinfo,
-                       const vec4_instruction *inst)
+                       enum shader_dispatch_mode dispatch_mode,
+                       unsigned stage, const vec4_instruction *inst)
 {
    /* Do not split some instructions that require special handling */
    switch (inst->opcode) {
@@ -2077,6 +2092,14 @@ get_lowered_simd_width(const struct gen_device_info *devinfo,
             continue;
          if (inst->size_read(i) <= REG_SIZE)
             lowered_width = MIN2(lowered_width, 4);
+
+         /* Interleaved attribute setups use a vertical stride of 0, which
+          * makes them hit the associated instruction decompression bug in gen7.
+          * Split them to prevent this.
+          */
+         if (inst->src[i].file == ATTR &&
+             stage_uses_interleaved_attributes(stage, dispatch_mode))
+            lowered_width = MIN2(lowered_width, 4);
       }
    }
 
@@ -2118,7 +2141,8 @@ vec4_visitor::lower_simd_width()
    bool progress = false;
 
    foreach_block_and_inst_safe(block, vec4_instruction, inst, cfg) {
-      const unsigned lowered_width = get_lowered_simd_width(devinfo, inst);
+      const unsigned lowered_width =
+         get_lowered_simd_width(devinfo, prog_data->dispatch_mode, stage, inst);
       assert(lowered_width <= inst->exec_size);
       if (lowered_width == inst->exec_size)
          continue;