i965: Add FS backend for builtin gl_SampleMask[]
authorAnuj Phogat <anuj.phogat@gmail.com>
Thu, 24 Oct 2013 23:21:13 +0000 (16:21 -0700)
committerAnuj Phogat <anuj.phogat@gmail.com>
Fri, 1 Nov 2013 23:01:48 +0000 (16:01 -0700)
V2:
   - Update comments
   - Add a special backend instructions to compute sample_mask.
   - Add a new variable uses_omask in brw_wm_prog_data.

V3:
   - Make changes to support simd16 mode.
   - Delete redundant AND instruction and handle the register
     stride in FS backend instruction.
Signed-off-by: Anuj Phogat <anuj.phogat@gmail.com>
Reviewed-by: Paul Berry <stereotype441@gmail.com>
src/mesa/drivers/dri/i965/brw_context.h
src/mesa/drivers/dri/i965/brw_defines.h
src/mesa/drivers/dri/i965/brw_fs.h
src/mesa/drivers/dri/i965/brw_fs_generator.cpp
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp

index 665807c8bf8b970ea9c79ed068d6043db5dec936..bec4d6b5541eac638cd762d292b66eeca3663c05 100644 (file)
@@ -384,6 +384,7 @@ struct brw_wm_prog_data {
    GLuint nr_pull_params;
    bool dual_src_blend;
    bool uses_pos_offset;
+   bool uses_omask;
    uint32_t prog_offset_16;
 
    /**
index e03ac583bfeed284af1f8036e72d67fe00e81228..bfea88a670ff13028da991f24436f3fd2c73fd91 100644 (file)
@@ -794,6 +794,7 @@ enum opcode {
    FS_OPCODE_VARYING_PULL_CONSTANT_LOAD_GEN7,
    FS_OPCODE_MOV_DISPATCH_TO_FLAGS,
    FS_OPCODE_DISCARD_JUMP,
+   FS_OPCODE_SET_OMASK,
    FS_OPCODE_SET_SAMPLE_ID,
    FS_OPCODE_SET_SIMD4X2_OFFSET,
    FS_OPCODE_PACK_HALF_2x16_SPLIT,
index 0ed8c05363484e12b7d8ced100b7731e9e92cb27..e9bf52f1f1180f709f5cfba61c5cdabecaaf1a32 100644 (file)
@@ -443,6 +443,7 @@ public:
 
    struct hash_table *variable_ht;
    fs_reg frag_depth;
+   fs_reg sample_mask;
    fs_reg outputs[BRW_MAX_DRAW_BUFFERS];
    unsigned output_components[BRW_MAX_DRAW_BUFFERS];
    fs_reg dual_src_output;
@@ -549,6 +550,10 @@ private:
                                                  struct brw_reg offset);
    void generate_mov_dispatch_to_flags(fs_inst *inst);
 
+   void generate_set_omask(fs_inst *inst,
+                           struct brw_reg dst,
+                           struct brw_reg sample_mask);
+
    void generate_set_sample_id(fs_inst *inst,
                                struct brw_reg dst,
                                struct brw_reg src0,
index 25530983f66c0e3d8fda1e06698bc78481c1c0f9..d67c4e4b3ae490f93d6de250a556067b94e3166e 100644 (file)
@@ -1068,6 +1068,44 @@ fs_generator::generate_set_simd4x2_offset(fs_inst *inst,
    brw_pop_insn_state(p);
 }
 
+/* Sets vstride=16, width=8, hstride=2 or vstride=0, width=1, hstride=0
+ * (when mask is passed as a uniform) of register mask before moving it
+ * to register dst.
+ */
+void
+fs_generator::generate_set_omask(fs_inst *inst,
+                                 struct brw_reg dst,
+                                 struct brw_reg mask)
+{
+   bool stride_8_8_1 =
+    (mask.vstride == BRW_VERTICAL_STRIDE_8 &&
+     mask.width == BRW_WIDTH_8 &&
+     mask.hstride == BRW_HORIZONTAL_STRIDE_1);
+
+   bool stride_0_1_0 =
+    (mask.vstride == BRW_VERTICAL_STRIDE_0 &&
+     mask.width == BRW_WIDTH_1 &&
+     mask.hstride == BRW_HORIZONTAL_STRIDE_0);
+
+   assert(stride_8_8_1 || stride_0_1_0);
+   assert(dst.type == BRW_REGISTER_TYPE_UW);
+
+   if (dispatch_width == 16)
+      dst = vec16(dst);
+   brw_push_insn_state(p);
+   brw_set_compression_control(p, BRW_COMPRESSION_NONE);
+   brw_set_mask_control(p, BRW_MASK_DISABLE);
+
+   if (stride_8_8_1) {
+      brw_MOV(p, dst, stride(retype(brw_vec1_reg(mask.file, mask.nr, 0),
+                                    dst.type), 16, 8, 2));
+   } else if (stride_0_1_0) {
+      brw_MOV(p, dst, stride(retype(brw_vec1_reg(mask.file, mask.nr, 0),
+                                    dst.type), 0, 1, 0));
+   }
+   brw_pop_insn_state(p);
+}
+
 /* Sets vstride=1, width=4, hstride=0 of register src1 during
  * the ADD instruction.
  */
@@ -1666,6 +1704,10 @@ fs_generator::generate_code(exec_list *instructions)
          generate_set_simd4x2_offset(inst, dst, src[0]);
          break;
 
+      case FS_OPCODE_SET_OMASK:
+         generate_set_omask(inst, dst, src[0]);
+         break;
+
       case FS_OPCODE_SET_SAMPLE_ID:
          generate_set_sample_id(inst, dst, src[0], src[1]);
          break;
index 09936374fd2d02b55373dd7ffc91b93d0add5f8e..dd606718b66fd4bb98449ca3d239ed81c2085c44 100644 (file)
@@ -82,6 +82,8 @@ fs_visitor::visit(ir_variable *ir)
         }
       } else if (ir->location == FRAG_RESULT_DEPTH) {
         this->frag_depth = *reg;
+      } else if (ir->location == FRAG_RESULT_SAMPLE_MASK) {
+         this->sample_mask = *reg;
       } else {
         /* gl_FragData or a user-defined FS output */
         assert(ir->location >= FRAG_RESULT_DATA0 &&
@@ -2526,6 +2528,16 @@ fs_visitor::emit_fb_writes()
       pop_force_uncompressed();
    }
 
+   c->prog_data.uses_omask =
+      fp->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_SAMPLE_MASK);
+   if(c->prog_data.uses_omask) {
+      this->current_annotation = "FB write oMask";
+      assert(this->sample_mask.file != BAD_FILE);
+      /* Hand over gl_SampleMask. Only lower 16 bits are relevant. */
+      emit(FS_OPCODE_SET_OMASK, fs_reg(MRF, nr, BRW_REGISTER_TYPE_UW), this->sample_mask);
+      nr += 1;
+   }
+
    /* Reserve space for color. It'll be filled in per MRT below. */
    int color_mrf = nr;
    nr += 4 * reg_width;