i965/fs: Allow specifying arbitrary quarter control to FIND_LIVE_CHANNEL.
authorFrancisco Jerez <currojerez@riseup.net>
Fri, 20 May 2016 23:25:42 +0000 (16:25 -0700)
committerFrancisco Jerez <currojerez@riseup.net>
Sat, 28 May 2016 06:29:04 +0000 (23:29 -0700)
This makes FIND_LIVE_CHANNEL behave like a normal instruction for
non-zero quarter control.  On Gen8+ we just leave the quarter control
field of the emitted FBL instruction set to the default value so the
hardware applies the expected shift to the execution mask signals.  On
Gen7 we apply the offset manually by specifying a non-zero subregister
offset in the source region of the FBL instruction.

Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
src/mesa/drivers/dri/i965/brw_eu_emit.c

index 1ca860a79c6c2489347597acef40c80588a2e4c1..2a3b0b03d8040560503cc6cd0014c930f627f101 100644 (file)
@@ -3332,6 +3332,7 @@ brw_find_live_channel(struct brw_codegen *p, struct brw_reg dst)
 {
    const struct brw_device_info *devinfo = p->devinfo;
    const unsigned exec_size = 1 << brw_inst_exec_size(devinfo, p->current);
+   const unsigned qtr_control = brw_inst_qtr_control(devinfo, p->current);
    brw_inst *inst;
 
    assert(devinfo->gen >= 7);
@@ -3352,14 +3353,13 @@ brw_find_live_channel(struct brw_codegen *p, struct brw_reg dst)
                         retype(brw_mask_reg(0), BRW_REGISTER_TYPE_UD));
 
          /* Quarter control has the effect of magically shifting the value of
-          * this register.  Make sure it's set to zero.
+          * this register so you'll get the first active channel relative to
+          * the specified quarter control as result.
           */
-         brw_inst_set_qtr_control(devinfo, inst, GEN6_COMPRESSION_1Q);
       } else {
-         const struct brw_reg flag = retype(brw_flag_reg(1, 0),
-                                            BRW_REGISTER_TYPE_UD);
+         const struct brw_reg flag = brw_flag_reg(1, 0);
 
-         brw_MOV(p, flag, brw_imm_ud(0));
+         brw_MOV(p, retype(flag, BRW_REGISTER_TYPE_UD), brw_imm_ud(0));
 
          /* Run enough instructions returning zero with execution masking and
           * a conditional modifier enabled in order to get the full execution
@@ -3373,13 +3373,18 @@ brw_find_live_channel(struct brw_codegen *p, struct brw_reg dst)
             inst = brw_MOV(p, retype(brw_null_reg(), BRW_REGISTER_TYPE_UW),
                            brw_imm_uw(0));
             brw_inst_set_mask_control(devinfo, inst, BRW_MASK_ENABLE);
-            brw_inst_set_group(devinfo, inst, lower_size * i);
+            brw_inst_set_group(devinfo, inst, lower_size * i + 8 * qtr_control);
             brw_inst_set_cond_modifier(devinfo, inst, BRW_CONDITIONAL_Z);
             brw_inst_set_flag_reg_nr(devinfo, inst, 1);
             brw_inst_set_exec_size(devinfo, inst, cvt(lower_size) - 1);
          }
 
-         brw_FBL(p, vec1(dst), flag);
+         /* Find the first bit set in the exec_size-wide portion of the flag
+          * register that was updated by the last sequence of MOV
+          * instructions.
+          */
+         const enum brw_reg_type type = brw_int_type(exec_size / 8, false);
+         brw_FBL(p, vec1(dst), byte_offset(retype(flag, type), qtr_control));
       }
    } else {
       brw_set_default_mask_control(p, BRW_MASK_DISABLE);