<div dir="ltr">On 25 October 2013 16:45, Anuj Phogat <span dir="ltr"><<a href="mailto:anuj.phogat@gmail.com" target="_blank">anuj.phogat@gmail.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">V2:<br>
   - Update comments<br>
   - Make changes to support simd16 mode.<br>
   - Add compute_sample_id variables in brw_wm_prog_key<br>
   - Add a special backend instruction to compute sample_id.<br>
<br>
Signed-off-by: Anuj Phogat <<a href="mailto:anuj.phogat@gmail.com" target="_blank">anuj.phogat@gmail.com</a>><br>
---<br>
 src/mesa/drivers/dri/i965/brw_defines.h        |  1 +<br>
 src/mesa/drivers/dri/i965/brw_fs.cpp           | 49 ++++++++++++++++++++++++++<br>
 src/mesa/drivers/dri/i965/brw_fs.h             |  7 ++++<br>
 src/mesa/drivers/dri/i965/brw_fs_generator.cpp | 27 ++++++++++++++<br>
 src/mesa/drivers/dri/i965/brw_fs_visitor.cpp   |  2 ++<br>
 src/mesa/drivers/dri/i965/brw_wm.c             |  6 ++++<br>
 src/mesa/drivers/dri/i965/brw_wm.h             |  1 +<br>
 7 files changed, 93 insertions(+)<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h<br>
index 5ba9d45..f3c994b 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_defines.h<br>
+++ b/src/mesa/drivers/dri/i965/brw_defines.h<br>
@@ -788,6 +788,7 @@ enum opcode {<br>
    FS_OPCODE_VARYING_PULL_CONSTANT_LOAD_GEN7,<br>
    FS_OPCODE_MOV_DISPATCH_TO_FLAGS,<br>
    FS_OPCODE_DISCARD_JUMP,<br>
+   FS_OPCODE_SET_SAMPLE_ID,<br>
    FS_OPCODE_SET_SIMD4X2_OFFSET,<br>
    FS_OPCODE_PACK_HALF_2x16_SPLIT,<br>
    FS_OPCODE_UNPACK_HALF_2x16_SPLIT_X,<br>
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
index 0f8213e..5773c6f 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
@@ -1176,6 +1176,55 @@ fs_visitor::emit_samplepos_setup(ir_variable *ir)<br>
    return reg;<br>
 }<br>
<br>
+fs_reg *<br>
+fs_visitor::emit_sampleid_setup(ir_variable *ir)<br>
+{<br>
+   assert(brw->gen >= 6);<br>
+<br>
+   this->current_annotation = "compute sample id";<br>
+   fs_reg *reg = new(this->mem_ctx) fs_reg(this, ir->type);<br>
+<br>
+   if (c->key.compute_sample_id) {<br>
+      fs_reg t1 = fs_reg(this, glsl_type::int_type);<br>
+      fs_reg t2 = fs_reg(this, glsl_type::int_type);<br>
+      t2.type = BRW_REGISTER_TYPE_UW;<br>
+<br>
+      /* The PS will be run in MSDISPMODE_PERSAMPLE. For example with<br>
+       * 8x multisampling, subspan 0 will represent sample N (where N<br>
+       * is 0, 2, 4 or 6), subspan 1 will represent sample 1, 3, 5 or<br>
+       * 7. We can find the value of N by looking at R0.0 bits 7:6<br>
+       * ("Starting Sample Pair Index (SSPI)") and multiplying by two<br>
+       * (since samples are always delivered in pairs). That is, we<br>
+       * compute 2*((R0.0 & 0xc0) >> 6) == (R0.0 & 0xc0) >> 5. Then<br>
+       * we need to add N to the sequence (0, 0, 0, 0, 1, 1, 1, 1) in<br>
+       * case of SIMD8 and sequence (0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2,<br>
+       * 2, 3, 3, 3, 3) in case of SIMD16. We compute this sequence by<br>
+       * populating a temporary variable with the sequence (0, 1, 2, 3),<br>
+       * and then reading from it using vstride=1, width=4, hstride=0.<br>
+       * These computations hold good for 4x multisampling as well.<br>
+       */<br>
+      emit(BRW_OPCODE_AND, t1,<br>
+           fs_reg(retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_D)),<br>
+           fs_reg(brw_imm_d(0xc0)));<br>
+      emit(BRW_OPCODE_SHR, t1, t1, fs_reg(5));<br>
+      /* This works for both SIMD8 and SIMD16 */<br>
+      emit(MOV(t2, brw_imm_v(0x3210)));<br></blockquote><div><br></div><div>These three instructions need to be emitted with force_writemask_all = true, just in case the fragment shader is dispatched with channel 0 disabled.<br>

</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      /* This special instruction takes care of setting vstride=1,<br>
+       * width=4, hstride=0 of t2 during an ADD instruction.<br>
+       */<br>
+      emit(FS_OPCODE_SET_SAMPLE_ID, *reg, t1, t2);<br></blockquote><div><br></div><div>I don't believe this will work, because type conversions can only be done in MOV instructions.  reg and t1 are UD, but FS_OPCODE_SET_SAMPLE_ID is going to cast t2 as UW.  Have you tried running this code in the simulator to see if it complains?<br>

<br></div><div>I believe what you need to do is use a MOV to copy the (0, 1, 2, 3) sequence to a full-size UD register, and then do the ADD as a final instruction.<br><br></div><div>(Note that the reason this wasn't necessary in blorp is that blorp uses UW for a lot of its temporary registers, so in the corresponding blorp code there's no type conversion going on).<br>

</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+   }<br>
+   else {<br></blockquote><div><br></div><div>Style nit-pick: generally we put "} else {" on a single line.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


+      /* As per GL_ARB_sample_shading specification:<br>
+       * "When rendering to a non-multisample buffer, or if multisample<br>
+       *  rasterization is disabled, gl_SampleID will always be zero."<br>
+       */<br>
+      emit(BRW_OPCODE_MOV, *reg, fs_reg(0));<br>
+   }<br>
+<br>
+   return reg;<br>
+}<br>
+<br>
 fs_reg<br>
 fs_visitor::fix_math_operand(fs_reg src)<br>
 {<br>
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h<br>
index db5df39..8a1a414 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_fs.h<br>
+++ b/src/mesa/drivers/dri/i965/brw_fs.h<br>
@@ -334,6 +334,7 @@ public:<br>
                          bool is_centroid);<br>
    fs_reg *emit_frontfacing_interpolation(ir_variable *ir);<br>
    fs_reg *emit_samplepos_setup(ir_variable *ir);<br>
+   fs_reg *emit_sampleid_setup(ir_variable *ir);<br>
    fs_reg *emit_general_interpolation(ir_variable *ir);<br>
    void emit_interpolation_setup_gen4();<br>
    void emit_interpolation_setup_gen6();<br>
@@ -538,6 +539,12 @@ private:<br>
                                                  struct brw_reg index,<br>
                                                  struct brw_reg offset);<br>
    void generate_mov_dispatch_to_flags(fs_inst *inst);<br>
+<br>
+   void generate_set_sample_id(fs_inst *inst,<br>
+                               struct brw_reg dst,<br>
+                               struct brw_reg src0,<br>
+                               struct brw_reg src1);<br>
+<br>
    void generate_set_simd4x2_offset(fs_inst *inst,<br>
                                     struct brw_reg dst,<br>
                                     struct brw_reg offset);<br>
diff --git a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp<br>
index fa15f7b..4f15ed7 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp<br>
+++ b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp<br>
@@ -1024,6 +1024,29 @@ fs_generator::generate_set_simd4x2_offset(fs_inst *inst,<br>
    brw_pop_insn_state(p);<br>
 }<br>
<br>
+/* Sets vstride=1, width=4, hstride=0 of register src1 during<br>
+ * the ADD instruction.<br>
+ */<br>
+void<br>
+fs_generator::generate_set_sample_id(fs_inst *inst,<br>
+                                     struct brw_reg dst,<br>
+                                     struct brw_reg src0,<br>
+                                     struct brw_reg src1)<br>
+{<br>
+   assert(dst.type == BRW_REGISTER_TYPE_D ||<br>
+          dst.type == BRW_REGISTER_TYPE_UD);<br>
+   assert(src0.type == BRW_REGISTER_TYPE_D ||<br>
+          src0.type == BRW_REGISTER_TYPE_UD);<br>
+   if (dispatch_width == 16)<br>
+      dst = vec16(dst);<br>
+   brw_push_insn_state(p);<br>
+   brw_set_compression_control(p, BRW_COMPRESSION_NONE);<br>
+   brw_set_mask_control(p, BRW_MASK_DISABLE);<br>
+   brw_ADD(p, dst, src0, stride(retype(brw_vec1_reg(src1.file, <a href="http://src1.nr" target="_blank">src1.nr</a>, 0),<br>
+                                       BRW_REGISTER_TYPE_UW), 1, 4, 0)); <br></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+   brw_pop_insn_state(p);<br>
+}<br>
+<br>
 /**<br>
  * Change the register's data type from UD to W, doubling the strides in order<br>
  * to compensate for halving the data type width.<br>
@@ -1553,6 +1576,10 @@ fs_generator::generate_code(exec_list *instructions)<br>
          generate_set_simd4x2_offset(inst, dst, src[0]);<br>
          break;<br>
<br>
+      case FS_OPCODE_SET_SAMPLE_ID:<br>
+         generate_set_sample_id(inst, dst, src[0], src[1]);<br>
+         break;<br>
+<br>
       case FS_OPCODE_PACK_HALF_2x16_SPLIT:<br>
           generate_pack_half_2x16_split(inst, dst, src[0], src[1]);<br>
           break;<br>
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp<br>
index 51972fe..7a6a0b5 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp<br>
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp<br>
@@ -129,6 +129,8 @@ fs_visitor::visit(ir_variable *ir)<br>
    } else if (ir->mode == ir_var_system_value) {<br>
       if (!strcmp(ir->name, "gl_SamplePosition")) {<br>
         reg = emit_samplepos_setup(ir);<br>
+      } else if (!strcmp(ir->name, "gl_SampleID")) {<br>
+        reg = emit_sampleid_setup(ir);<br></blockquote><div><br></div><div>As in the previous patch, I believe you can just use ir->location rather than doing a strcmp on the name.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


       }<br>
    }<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c<br>
index d2a5a9f..afb62fb 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_wm.c<br>
+++ b/src/mesa/drivers/dri/i965/brw_wm.c<br>
@@ -367,6 +367,7 @@ static void brw_wm_populate_key( struct brw_context *brw,<br>
    GLuint lookup = 0;<br>
    GLuint line_aa;<br>
    bool program_uses_dfdy = fp->program.UsesDFdy;<br>
+   bool multisample_fbo = ctx->DrawBuffer->Visual.samples > 1;<br>
<br>
    memset(key, 0, sizeof(*key));<br>
<br>
@@ -489,6 +490,11 @@ static void brw_wm_populate_key( struct brw_context *brw,<br>
       _mesa_get_min_invocations_per_fragment(ctx, &fp->program) > 1 &&<br>
       fp->program.Base.SystemValuesRead & SYSTEM_BIT_SAMPLE_POS;<br>
<br>
+   key->compute_sample_id =<br>
+      multisample_fbo &&<br>
+      ctx->Multisample.Enabled &&<br>
+      fp->program.Base.SystemValuesRead & SYSTEM_BIT_SAMPLE_ID;<br></blockquote><div><br></div><div>I always forget the precedence rules between & and &&.  Can we put parenthesis around (fp->program.Base.SystemValuesRead & SYSTEM_BIT_SAMPLE_ID) just to be on the safe side?<br>
</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
    /* BRW_NEW_VUE_MAP_GEOM_OUT */<br>
    if (brw->gen < 6 || _mesa_bitcount_64(fp->program.Base.InputsRead &<br>
                                          BRW_FS_VARYING_INPUT_MASK) > 16)<br>
diff --git a/src/mesa/drivers/dri/i965/brw_wm.h b/src/mesa/drivers/dri/i965/brw_wm.h<br>
index eb740ad..f5823f4 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_wm.h<br>
+++ b/src/mesa/drivers/dri/i965/brw_wm.h<br>
@@ -66,6 +66,7 @@ struct brw_wm_prog_key {<br>
    GLuint render_to_fbo:1;<br>
    GLuint clamp_fragment_color:1;<br>
    GLuint compute_pos_offset:1;<br>
+   GLuint compute_sample_id:1;<br>
    GLuint line_aa:2;<br>
    GLuint high_quality_derivatives:1;<br>
<span><font color="#888888"><br>
--<br>
1.8.1.4<br>
<br>
</font></span></blockquote></div><br></div></div>