[Mesa-dev] [PATCH 19/22] i965/fs/gen6: Support for sampling stencil with msaa coordinates

Topi Pohjolainen topi.pohjolainen at intel.com
Mon Jun 9 00:45:53 PDT 2014


Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
---
 src/mesa/drivers/dri/i965/brw_fs.h               |  2 +-
 src/mesa/drivers/dri/i965/brw_fs_fp.cpp          |  3 +-
 src/mesa/drivers/dri/i965/brw_fs_stencil_tex.cpp | 92 +++++++++++++++++++++++-
 src/mesa/drivers/dri/i965/brw_fs_visitor.cpp     | 23 ++++--
 4 files changed, 110 insertions(+), 10 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index e1f540d..eae242b 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -185,7 +185,7 @@ public:
 			      fs_reg shadow_comp, fs_reg lod, fs_reg lod2);
    fs_inst *emit_texture_gen5(ir_texture *ir, fs_reg dst, fs_reg coordinate,
                               fs_reg shadow_comp, fs_reg lod, fs_reg lod2,
-                              fs_reg sample_index);
+                              fs_reg sample_index, int sampler);
    fs_inst *emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate,
                               fs_reg shadow_comp, fs_reg lod, fs_reg lod2,
                               fs_reg sample_index, fs_reg mcs, int sampler);
diff --git a/src/mesa/drivers/dri/i965/brw_fs_fp.cpp b/src/mesa/drivers/dri/i965/brw_fs_fp.cpp
index ba5514a..f34b2ad 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_fp.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_fp.cpp
@@ -496,7 +496,8 @@ fs_visitor::emit_fragment_program_code()
          if (brw->gen >= 7) {
             inst = emit_texture_gen7(ir, dst, coordinate, shadow_c, lod, dpdy, sample_index, fs_reg(0u), fpi->TexSrcUnit);
          } else if (brw->gen >= 5) {
-            inst = emit_texture_gen5(ir, dst, coordinate, shadow_c, lod, dpdy, sample_index);
+            inst = emit_texture_gen5(ir, dst, coordinate, shadow_c, lod, dpdy,
+                                     sample_index, fpi->TexSrcUnit);
          } else {
             inst = emit_texture_gen4(ir, dst, coordinate, shadow_c, lod, dpdy);
          }
diff --git a/src/mesa/drivers/dri/i965/brw_fs_stencil_tex.cpp b/src/mesa/drivers/dri/i965/brw_fs_stencil_tex.cpp
index 2d813e9..cd746db 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_stencil_tex.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_stencil_tex.cpp
@@ -65,6 +65,78 @@
 namespace {
 
 /**
+ * Emit instructions transforming pixel coordinates into interleaved (IMS)
+ * sample coordinates. This is needed when a multisampled surface is textured
+ * without the hardware support. Unfortunately on generations from five to
+ * seven the sampling engine cannot does not support W-tiled stencil and part
+ * of the needed workaround is to access the individual samples manually.
+ *
+ * Samples are organised as follows:
+ *
+ * ---------------------------------   -----------------
+ * | 0 | 0 | 1 | 1 | 4 | 4 | 5 | 5 |   | 0 | 0 | 1 | 1 |
+ * | 0 | 0 | 1 | 1 | 4 | 4 | 5 | 5 |   | 0 | 0 | 1 | 1 |
+ * | 2 | 2 | 3 | 3 | 6 | 6 | 7 | 7 |   | 2 | 2 | 3 | 3 |
+ * | 2 | 2 | 3 | 3 | 6 | 6 | 7 | 7 |   | 2 | 2 | 3 | 3 |
+ * ---------------------------------   -----------------
+ *               8X                           4X
+ *
+ * This allows for the following conversions where S represents the sample
+ * index:
+ *
+ * 4:    X' = (X & ~0b1) << 1 | (S & 0b1) << 1 | (X & 0b1)
+ *       Y' = (Y & ~0b1) << 1 | (S & 0b10)     | (Y & 0b1)
+ *
+ * 8:    X' = (X & ~0b1) << 2 | (S & 0b100) | (S & 0b1) << 1 | (X & 0b1)
+ *       Y' = (Y & ~0b1) << 1 | (S & 0b10)  | (Y & 0b1)
+ *
+ * The surface is setup for the sampling engine to return one 2x2 block
+ * for 4X-case and two 2x2 blocks for 8X-case. The former contains the samples
+ * for one index while the latter for an index pair - possible pairs are
+ * (0,1), (2,3), (4,5) and (6,7).
+ *
+ * The lowest bits in the coordinates are ignored (set to zero) in order to
+ * get the top left corner of the block(s). Similarly the lowest bit of the
+ * smaple index is ignored in the 8X case.
+ *
+ * The motivation for the arrangement is to not impose any additional
+ * limitations for the texture sizes. Without one is forced to supply upscaled
+ * width and height to the sampling engine thus restricting the size of the
+ * original texture.
+ */
+static void
+emit_encode_ims(fs_emitter *e, const fs_reg& coord, const fs_reg &s,
+                unsigned num_samples)
+{
+   fs_reg tmp(e, glsl_type::uint_type);
+   fs_reg x(coord);
+   fs_reg y(offset(coord, 1));
+
+   assert(num_samples == 4 || num_samples == 8);
+
+   e->emit(e->AND(tmp, x, fs_reg(0x1))); /* (X & 0b1) */
+   e->emit(e->AND(x, x, fs_reg(0xfffe))); /* (X & ~0b1) */
+   e->emit(e->SHL(x, x, fs_reg(num_samples / 4))); /* (X & ~0b1) << 1:2 */
+   e->emit(e->OR(x, x, tmp)); /* (X & ~0b1) << 1:2 | (X & 0b1) */
+
+   if (num_samples == 8) {
+      e->emit(e->AND(tmp, s, fs_reg(4))); /* S & 0b100 */
+      e->emit(e->OR(x, x, tmp)); /* X' = X' | (S & 0b100) */
+   } else {
+      e->emit(e->AND(tmp, s, fs_reg(0x1))); /* (S & 0b1) */
+      e->emit(e->SHL(tmp, tmp, fs_reg(0x1))); /* (S & 0b1) << 1 */
+      e->emit(e->OR(x, x, tmp)); /* X' = X' | (S & 0b1) << 1 */
+   }
+
+   e->emit(e->AND(tmp, y, fs_reg(0x1))); /* (Y & 0b1) */
+   e->emit(e->AND(y, y, fs_reg(0xfffe))); /* (Y & ~0b1) */
+   e->emit(e->SHL(y, y, fs_reg(1))); /* (Y & ~0b1) << 1 */
+   e->emit(e->OR(y, y, tmp)); /* (Y & ~0b1) << 1 | (Y & 0b1) */
+   e->emit(e->AND(tmp, s, fs_reg(0x2))); /* (S & 0b10) */
+   e->emit(e->OR(y, y, tmp)); /* Y' = Y' | (S & 0b10) */
+}
+
+/**
  * Emit translation of pixel coordinates src_x and src_y in W-tiled layout
  * to corresponding coordinates dst_x and dst_y in Y-tiled layout.
  * Note that source and destination registers cannot overlap.
@@ -377,7 +449,7 @@ fs_stencil_texturing::emit_w_to_y_tiling(struct brw_fragment_program *fp,
    e->emit(e->AND(y_lowest_bit, offset(*coord, 1), fs_reg(0x1)));
 
    if (op == ir_txf_ms) {
-      assert(!"Multisampled stencil texturing is not supported");
+      emit_encode_ims(e, *coord, sample_index, num_samples);
    } else {
       offset_to_w_tiled_miplevel(lod_ud);
    
@@ -387,8 +459,11 @@ fs_stencil_texturing::emit_w_to_y_tiling(struct brw_fragment_program *fp,
 
    emit_translate_w_to_y_tiling(e, *coord);
 
-   /* Modify the pixel coordinates to point to the 2x2 block. */
-   e->emit(e->SHR(*coord, *coord, 2));
+   /* Modify the pixel coordinates to point to the 2x2 block. In case of
+    * 8X there are two 2x2 blocks side by side containg samples for one
+    * 2x2 pixel block.
+    */
+   e->emit(e->SHR(*coord, *coord, fs_reg(num_samples == 8 ? 3 : 2)));
 }
 
 void
@@ -397,6 +472,17 @@ fs_stencil_texturing::emit_pick_w_tiled_sample(const fs_reg& samples,
 {
    fs_inst *inst;
 
+   if (num_samples == 8) {
+      /* Choose between the pair of indices (0,1), (2,3), (4,5) or (6,7). In
+       * case the latter is needed simply move the green to the red channel.
+       */
+      e->emit(e->AND(sample_index, sample_index, fs_reg(1)));
+      inst = e->emit(BRW_OPCODE_CMP, reg_null_f, sample_index, fs_reg(0));
+      inst->conditional_mod = BRW_CONDITIONAL_NZ;
+      inst = e->emit(e->MOV(samples, offset(samples, 1)));
+      inst->predicate = BRW_PREDICATE_NORMAL;
+   }
+
    inst = e->emit(BRW_OPCODE_CMP, reg_null_f, y_lowest_bit, fs_reg(0));
    inst->conditional_mod = BRW_CONDITIONAL_NZ;
    inst = e->emit(e->SHR(samples, samples, fs_reg(16)));
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index f6bb010..30a3b84 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -1125,6 +1125,19 @@ fs_visitor::emit_texture_gen4(ir_texture *ir, fs_reg dst, fs_reg coordinate,
    return inst;
 }
 
+static enum ir_texture_opcode
+resolve_texture_op(const struct brw_sampler_prog_key_data *key, int sampler,
+                   enum ir_texture_opcode op)
+{
+   /* In case of stencil, surfaces are configured as single sampled and
+    * coordinates are translated for texel fetches.
+    */
+   if (key->num_w_tiled_samples[sampler])
+      return ir_txf;
+
+   return op;
+}
+
 /* gen5's sampler has slots for u, v, r, array index, then optional
  * parameters like shadow comparitor or LOD bias.  If optional
  * parameters aren't present, those base slots are optional and don't
@@ -1136,7 +1149,7 @@ fs_visitor::emit_texture_gen4(ir_texture *ir, fs_reg dst, fs_reg coordinate,
 fs_inst *
 fs_visitor::emit_texture_gen5(ir_texture *ir, fs_reg dst, fs_reg coordinate,
                               fs_reg shadow_c, fs_reg lod, fs_reg lod2,
-                              fs_reg sample_index)
+                              fs_reg sample_index, int sampler)
 {
    int mlen = 0;
    int base_mrf = 2;
@@ -1169,7 +1182,7 @@ fs_visitor::emit_texture_gen5(ir_texture *ir, fs_reg dst, fs_reg coordinate,
    }
 
    fs_inst *inst = NULL;
-   switch (ir->op) {
+   switch (resolve_texture_op(&key->tex, sampler, ir->op)) {
    case ir_tex:
       inst = emit(SHADER_OPCODE_TEX, dst);
       break;
@@ -1295,7 +1308,7 @@ fs_visitor::emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate,
    bool coordinate_done = false;
 
    /* Set up the LOD info */
-   switch (ir->op) {
+   switch (resolve_texture_op(&key->tex, sampler, ir->op)) {
    case ir_tex:
    case ir_lod:
       break;
@@ -1422,7 +1435,7 @@ fs_visitor::emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate,
 
    /* Generate the SEND */
    fs_inst *inst = NULL;
-   switch (ir->op) {
+   switch (resolve_texture_op(&key->tex, sampler, ir->op)) {
    case ir_tex: inst = emit(SHADER_OPCODE_TEX, dst, payload); break;
    case ir_txb: inst = emit(FS_OPCODE_TXB, dst, payload); break;
    case ir_txl: inst = emit(SHADER_OPCODE_TXL, dst, payload); break;
@@ -1712,7 +1725,7 @@ fs_visitor::visit(ir_texture *ir)
                                lod, lod2, sample_index, mcs, sampler);
    } else if (brw->gen >= 5) {
       inst = emit_texture_gen5(ir, dst, coordinate, shadow_comparitor,
-                               lod, lod2, sample_index);
+                               lod, lod2, sample_index, sampler);
    } else {
       inst = emit_texture_gen4(ir, dst, coordinate, shadow_comparitor,
                                lod, lod2);
-- 
1.8.3.1



More information about the mesa-dev mailing list