[Mesa-dev] [PATCH 2/8] i965/msaa: Add an enum to describe MSAA layout.

Paul Berry stereotype441 at gmail.com
Fri Jul 6 15:29:39 PDT 2012


>From the Ivy Bridge PRM, Vol 1 Part 1, p112:

    There are three types of multisampled surface layouts designated
    as follows:
      - IMS Interleaved Multisampled Surface
      - CMS Compressed Mulitsampled Surface
      - UMS Uncompressed Multisampled Surface

Previously, the i965 driver only used IMS and UMS formats, and
distinguished beetween them using the boolean
intel_mipmap_tree::msaa_is_interleaved.  To facilitate adding support
for the CMS format, this patch replaces that boolean (and other
booleans derived from it) with an enum
INTEL_MSAA_LAYOUT_{IMS,CMS,UMS}.  It also updates the terminology used
in comments throughout the driver to match the IMS/CMS/UMS terminology
used in the PRM.  CMS layout is not yet used.

The enum has a fourth possible value, INTEL_MSAA_LAYOUT_NONE, which is
used for non-multisampled surfaces.
---
 src/mesa/drivers/dri/i965/brw_blorp.cpp           |    1 +
 src/mesa/drivers/dri/i965/brw_blorp.h             |   32 ++--
 src/mesa/drivers/dri/i965/brw_blorp_blit.cpp      |  190 ++++++++++++++-------
 src/mesa/drivers/dri/i965/brw_tex_layout.c        |   10 +-
 src/mesa/drivers/dri/i965/brw_wm_surface_state.c  |    2 +-
 src/mesa/drivers/dri/i965/gen7_wm_surface_state.c |    4 +-
 src/mesa/drivers/dri/intel/intel_mipmap_tree.c    |   68 ++++----
 src/mesa/drivers/dri/intel/intel_mipmap_tree.h    |   48 +++++-
 src/mesa/drivers/dri/intel/intel_tex_image.c      |    2 +-
 src/mesa/drivers/dri/intel/intel_tex_validate.c   |    2 +-
 10 files changed, 229 insertions(+), 130 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_blorp.cpp b/src/mesa/drivers/dri/i965/brw_blorp.cpp
index afb4530..9017e4d 100644
--- a/src/mesa/drivers/dri/i965/brw_blorp.cpp
+++ b/src/mesa/drivers/dri/i965/brw_blorp.cpp
@@ -61,6 +61,7 @@ brw_blorp_surface_info::set(struct brw_context *brw,
    this->num_samples = mt->num_samples;
    this->array_spacing_lod0 = mt->array_spacing_lod0;
    this->map_stencil_as_y_tiled = false;
+   this->msaa_layout = mt->msaa_layout;
 
    switch (mt->format) {
    case MESA_FORMAT_S8:
diff --git a/src/mesa/drivers/dri/i965/brw_blorp.h b/src/mesa/drivers/dri/i965/brw_blorp.h
index 4259d9c..053eef7 100644
--- a/src/mesa/drivers/dri/i965/brw_blorp.h
+++ b/src/mesa/drivers/dri/i965/brw_blorp.h
@@ -97,6 +97,12 @@ void set(struct brw_context *brw,
     * surface.  Should correspond to one of the BRW_SURFACEFORMAT_* enums.
     */
    uint32_t brw_surfaceformat;
+
+   /**
+    * For MSAA surfaces, MSAA layout that should be used when setting up the
+    * surface state for this surface.
+    */
+   intel_msaa_layout msaa_layout;
 };
 
 
@@ -192,38 +198,30 @@ struct brw_blorp_blit_prog_key
     */
    unsigned tex_samples;
 
-   /* If tex_samples > 0, whether or not the GPU pipeline will be configured
-    * to read from it as though it were an interleaved MSAA layout.  False if
-    * tex_samples == 0.
+   /* MSAA layout that has been configured in the surface state for texturing
+    * from.
     */
-   bool tex_interleaved;
+   intel_msaa_layout tex_layout;
 
    /* Actual number of samples per pixel in the source image. */
    unsigned src_samples;
 
-   /* If src_samples > 0, whether or not the source image uses an interleaved
-    * MSAA layout.  False if src_samples == 0.
-    */
-   bool src_interleaved;
+   /* Actual MSAA layout used by the source image. */
+   intel_msaa_layout src_layout;
 
    /* Number of samples per pixel that have been configured in the render
     * target.
     */
    unsigned rt_samples;
 
-   /* If rt_samples > 0, whether or not the GPU pipeline will be configured
-    * to write to it as though it were an interleaved MSAA layout.  False if
-    * rt_samples == 0.
-    */
-   bool rt_interleaved;
+   /* MSAA layout that has been configured in the render target. */
+   intel_msaa_layout rt_layout;
 
    /* Actual number of samples per pixel in the destination image. */
    unsigned dst_samples;
 
-   /* If dst_samples > 0, whether or not the destination image uses an
-    * interleaved MSAA layout.  False if dst_samples == 0.
-    */
-   bool dst_interleaved;
+   /* Actual MSAA layout used by the destination image. */
+   intel_msaa_layout dst_layout;
 
    /* True if the source image is W tiled.  If true, the surface state for the
     * source image must be configured as Y tiled, and tex_samples must be 0.
diff --git a/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp b/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp
index 0467607..ea98a66 100644
--- a/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp
+++ b/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp
@@ -288,22 +288,22 @@ enum sampler_message_arg
  *   offset = tile(tiling_format, encode_msaa(num_samples, layout, X, Y, S))
  *   (X, Y, S) = decode_msaa(num_samples, layout, detile(tiling_format, offset))
  *
- * For a single-sampled surface, or for a multisampled surface that stores
- * each sample in a different array slice, encode_msaa() and decode_msaa are
- * the identity function:
+ * For a single-sampled surface, or for a multisampled surface using
+ * INTEL_MSAA_LAYOUT_UMS, encode_msaa() and decode_msaa are the identity
+ * function:
  *
- *   encode_msaa(1, N/A, X, Y, 0) = (X, Y, 0)
- *   decode_msaa(1, N/A, X, Y, 0) = (X, Y, 0)
- *   encode_msaa(n, sliced, X, Y, S) = (X, Y, S)
- *   decode_msaa(n, sliced, X, Y, S) = (X, Y, S)
+ *   encode_msaa(1, NONE, X, Y, 0) = (X, Y, 0)
+ *   decode_msaa(1, NONE, X, Y, 0) = (X, Y, 0)
+ *   encode_msaa(n, UMS, X, Y, S) = (X, Y, S)
+ *   decode_msaa(n, UMS, X, Y, S) = (X, Y, S)
  *
- * For a 4x interleaved multisampled surface, encode_msaa() embeds the sample
- * number into bit 1 of the X and Y coordinates:
+ * For a 4x multisampled surface using INTEL_MSAA_LAYOUT_IMS, encode_msaa()
+ * embeds the sample number into bit 1 of the X and Y coordinates:
  *
- *   encode_msaa(4, interleaved, X, Y, S) = (X', Y', 0)
+ *   encode_msaa(4, IMS, X, Y, S) = (X', Y', 0)
  *     where X' = (X & ~0b1) << 1 | (S & 0b1) << 1 | (X & 0b1)
  *           Y' = (Y & ~0b1 ) << 1 | (S & 0b10) | (Y & 0b1)
- *   decode_msaa(4, interleaved, X, Y, 0) = (X', Y', S)
+ *   decode_msaa(4, IMS, X, Y, 0) = (X', Y', S)
  *     where X' = (X & ~0b11) >> 1 | (X & 0b1)
  *           Y' = (Y & ~0b11) >> 1 | (Y & 0b1)
  *           S = (Y & 0b10) | (X & 0b10) >> 1
@@ -419,8 +419,8 @@ private:
    void alloc_push_const_regs(int base_reg);
    void compute_frag_coords();
    void translate_tiling(bool old_tiled_w, bool new_tiled_w);
-   void encode_msaa(unsigned num_samples, bool interleaved);
-   void decode_msaa(unsigned num_samples, bool interleaved);
+   void encode_msaa(unsigned num_samples, intel_msaa_layout layout);
+   void decode_msaa(unsigned num_samples, intel_msaa_layout layout);
    void kill_if_outside_dst_rect();
    void translate_dst_to_src();
    void single_to_blend();
@@ -529,7 +529,7 @@ brw_blorp_blit_program::compile(struct brw_context *brw,
        */
       assert(!key->src_tiled_w);
       assert(key->tex_samples == key->src_samples);
-      assert(key->tex_interleaved == key->src_interleaved);
+      assert(key->tex_layout == key->src_layout);
       assert(key->tex_samples > 0);
    }
 
@@ -540,10 +540,15 @@ brw_blorp_blit_program::compile(struct brw_context *brw,
       assert(key->rt_samples > 0);
    }
 
-   /* Interleaved only makes sense on MSAA surfaces */
-   if (key->tex_interleaved) assert(key->tex_samples > 0);
-   if (key->src_interleaved) assert(key->src_samples > 0);
-   if (key->dst_interleaved) assert(key->dst_samples > 0);
+   /* Make sure layout is consistent with sample count */
+   assert((key->tex_layout == INTEL_MSAA_LAYOUT_NONE) ==
+          (key->tex_samples == 0));
+   assert((key->rt_layout == INTEL_MSAA_LAYOUT_NONE) ==
+          (key->rt_samples == 0));
+   assert((key->src_layout == INTEL_MSAA_LAYOUT_NONE) ==
+          (key->src_samples == 0));
+   assert((key->dst_layout == INTEL_MSAA_LAYOUT_NONE) ==
+          (key->dst_samples == 0));
 
    /* Set up prog_data */
    memset(&prog_data, 0, sizeof(prog_data));
@@ -571,12 +576,12 @@ brw_blorp_blit_program::compile(struct brw_context *brw,
     */
    if (rt_tiled_w != key->dst_tiled_w ||
        key->rt_samples != key->dst_samples ||
-       key->rt_interleaved != key->dst_interleaved) {
-      encode_msaa(key->rt_samples, key->rt_interleaved);
+       key->rt_layout != key->dst_layout) {
+      encode_msaa(key->rt_samples, key->rt_layout);
       /* Now (X, Y, S) = detile(rt_tiling, offset) */
       translate_tiling(rt_tiled_w, key->dst_tiled_w);
       /* Now (X, Y, S) = detile(dst_tiling, offset) */
-      decode_msaa(key->dst_samples, key->dst_interleaved);
+      decode_msaa(key->dst_samples, key->dst_layout);
    }
 
    /* Now (X, Y, S) = decode_msaa(dst_samples, detile(dst_tiling, offset)).
@@ -626,12 +631,12 @@ brw_blorp_blit_program::compile(struct brw_context *brw,
        */
       if (tex_tiled_w != key->src_tiled_w ||
           key->tex_samples != key->src_samples ||
-          key->tex_interleaved != key->src_interleaved) {
-         encode_msaa(key->src_samples, key->src_interleaved);
+          key->tex_layout != key->src_layout) {
+         encode_msaa(key->src_samples, key->src_layout);
          /* Now (X, Y, S) = detile(src_tiling, offset) */
          translate_tiling(key->src_tiled_w, tex_tiled_w);
          /* Now (X, Y, S) = detile(tex_tiling, offset) */
-         decode_msaa(key->tex_samples, key->tex_interleaved);
+         decode_msaa(key->tex_samples, key->tex_layout);
       }
 
       /* Now (X, Y, S) = decode_msaa(tex_samples, detile(tex_tiling, offset)).
@@ -801,7 +806,7 @@ brw_blorp_blit_program::translate_tiling(bool old_tiled_w, bool new_tiled_w)
       return;
 
    /* In the code that follows, we can safely assume that S = 0, because W
-    * tiling formats always use interleaved encoding.
+    * tiling formats always use IMS layout.
     */
    assert(s_is_zero);
 
@@ -887,15 +892,25 @@ brw_blorp_blit_program::translate_tiling(bool old_tiled_w, bool new_tiled_w)
  * (See brw_blorp_blit_program).
  */
 void
-brw_blorp_blit_program::encode_msaa(unsigned num_samples, bool interleaved)
+brw_blorp_blit_program::encode_msaa(unsigned num_samples,
+                                    intel_msaa_layout layout)
 {
-   if (num_samples == 0) {
+   switch (layout) {
+   case INTEL_MSAA_LAYOUT_NONE:
       /* No translation necessary, and S should already be zero. */
       assert(s_is_zero);
-   } else if (!interleaved) {
+      break;
+   case INTEL_MSAA_LAYOUT_CMS:
+      /* We can't compensate for compressed layout since at this point in the
+       * program we haven't read from the MCS buffer.
+       */
+      assert(!"Bad layout in encode_msaa");
+      break;
+   case INTEL_MSAA_LAYOUT_UMS:
       /* No translation necessary. */
-   } else {
-      /* encode_msaa(4, interleaved, X, Y, S) = (X', Y', 0)
+      break;
+   case INTEL_MSAA_LAYOUT_IMS:
+      /* encode_msaa(4, IMS, X, Y, S) = (X', Y', 0)
        *   where X' = (X & ~0b1) << 1 | (S & 0b1) << 1 | (X & 0b1)
        *         Y' = (Y & ~0b1 ) << 1 | (S & 0b10) | (Y & 0b1)
        */
@@ -918,6 +933,7 @@ brw_blorp_blit_program::encode_msaa(unsigned num_samples, bool interleaved)
       brw_OR(&func, Yp, t1, t2);
       SWAP_XY_AND_XPYP();
       s_is_zero = true;
+      break;
    }
 }
 
@@ -932,15 +948,25 @@ brw_blorp_blit_program::encode_msaa(unsigned num_samples, bool interleaved)
  * (See brw_blorp_blit_program).
  */
 void
-brw_blorp_blit_program::decode_msaa(unsigned num_samples, bool interleaved)
+brw_blorp_blit_program::decode_msaa(unsigned num_samples,
+                                    intel_msaa_layout layout)
 {
-   if (num_samples == 0) {
+   switch (layout) {
+   case INTEL_MSAA_LAYOUT_NONE:
       /* No translation necessary, and S should already be zero. */
       assert(s_is_zero);
-   } else if (!interleaved) {
+      break;
+   case INTEL_MSAA_LAYOUT_CMS:
+      /* We can't compensate for compressed layout since at this point in the
+       * program we don't have access to the MCS buffer.
+       */
+      assert(!"Bad layout in encode_msaa");
+      break;
+   case INTEL_MSAA_LAYOUT_UMS:
       /* No translation necessary. */
-   } else {
-      /* decode_msaa(4, interleaved, X, Y, 0) = (X', Y', S)
+      break;
+   case INTEL_MSAA_LAYOUT_IMS:
+      /* decode_msaa(4, IMS, X, Y, 0) = (X', Y', S)
        *   where X' = (X & ~0b11) >> 1 | (X & 0b1)
        *         Y' = (Y & ~0b11) >> 1 | (Y & 0b1)
        *         S = (Y & 0b10) | (X & 0b10) >> 1
@@ -960,6 +986,7 @@ brw_blorp_blit_program::decode_msaa(unsigned num_samples, bool interleaved)
       brw_OR(&func, S, t1, t2);
       s_is_zero = false;
       SWAP_XY_AND_XPYP();
+      break;
    }
 }
 
@@ -1248,6 +1275,40 @@ brw_blorp_coord_transform_params::setup(GLuint src0, GLuint dst0, GLuint dst1,
 }
 
 
+/**
+ * Determine which MSAA layout the GPU pipeline should be configured for,
+ * based on the chip generation, the number of samples, and the true layout of
+ * the image in memory.
+ */
+inline intel_msaa_layout
+compute_msaa_layout_for_pipeline(struct brw_context *brw, unsigned num_samples,
+                                 intel_msaa_layout true_layout)
+{
+   if (num_samples == 0) {
+      /* When configuring the GPU for non-MSAA, we can still accommodate IMS
+       * format buffers, by transforming coordinates appropriately.
+       */
+      assert(true_layout == INTEL_MSAA_LAYOUT_NONE ||
+             true_layout == INTEL_MSAA_LAYOUT_IMS);
+      return INTEL_MSAA_LAYOUT_NONE;
+   }
+
+   /* Prior to Gen7, all MSAA surfaces use IMS layout. */
+   if (brw->intel.gen == 6) {
+      assert(true_layout == INTEL_MSAA_LAYOUT_IMS);
+      return INTEL_MSAA_LAYOUT_IMS;
+   }
+
+   /* Since blorp uses color textures and render targets to do all its work
+    * (even when blitting stencil and depth data), we always have to configure
+    * the Gen7 GPU to use UMS or CMS layout on Gen7.
+    */
+   assert(true_layout == INTEL_MSAA_LAYOUT_UMS ||
+          true_layout == INTEL_MSAA_LAYOUT_CMS);
+   return true_layout;
+}
+
+
 brw_blorp_blit_params::brw_blorp_blit_params(struct brw_context *brw,
                                              struct intel_mipmap_tree *src_mt,
                                              struct intel_mipmap_tree *dst_mt,
@@ -1263,22 +1324,21 @@ brw_blorp_blit_params::brw_blorp_blit_params(struct brw_context *brw,
    memset(&wm_prog_key, 0, sizeof(wm_prog_key));
 
    if (brw->intel.gen > 6) {
-      /* Gen7 only supports interleaved MSAA surfaces for texturing with the
+      /* Gen7's texturing hardware only supports the IMS layout with the
        * ld2dms instruction (which blorp doesn't use).  So if the source is
-       * interleaved MSAA, we'll have to map it as a single-sampled texture
-       * and de-interleave the samples ourselves.
+       * IMS, we'll have to map it as a single-sampled texture and
+       * de-interleave the samples ourselves.
        */
-      if (src.num_samples > 0 && src_mt->msaa_is_interleaved)
+      if (src_mt->msaa_layout == INTEL_MSAA_LAYOUT_IMS)
          src.num_samples = 0;
 
-      /* Similarly, Gen7 only supports interleaved MSAA surfaces for depth and
-       * stencil render targets.  Blorp always maps its destination surface as
-       * a color render target (even if it's actually a depth or stencil
-       * buffer).  So if the destination is interleaved MSAA, we'll have to
-       * map it as a single-sampled texture and interleave the samples
-       * ourselves.
+      /* Similarly, Gen7's rendering hardware only supports the IMS layout for
+       * depth and stencil render targets.  Blorp always maps its destination
+       * surface as a color render target (even if it's actually a depth or
+       * stencil buffer).  So if the destination is IMS, we'll have to map it
+       * as a single-sampled texture and interleave the samples ourselves.
        */
-      if (dst.num_samples > 0 && dst_mt->msaa_is_interleaved)
+      if (dst_mt->msaa_layout == INTEL_MSAA_LAYOUT_IMS)
          dst.num_samples = 0;
    }
 
@@ -1324,21 +1384,19 @@ brw_blorp_blit_params::brw_blorp_blit_params(struct brw_context *brw,
    wm_prog_key.tex_samples = src.num_samples;
    wm_prog_key.rt_samples  = dst.num_samples;
 
-   /* tex_interleaved and rt_interleaved indicate whether or not the GPU
-    * pipeline will access the source and destination surfaces as though they
-    * use an interleaved layout.  Since blorp uses color textures and render
-    * targets to do all its work (even when blitting stencil and depth data),
-    * it will always use sliced layout on Gen7.  On Gen6, the MSAA layout is
-    * always interleaved.
+   /* tex_layout and rt_layout indicate the MSAA layout the GPU pipeline will
+    * use to access the source and destination surfaces.
     */
-   wm_prog_key.tex_interleaved = src.num_samples > 0 && brw->intel.gen == 6;
-   wm_prog_key.rt_interleaved = dst.num_samples > 0 && brw->intel.gen == 6;
+   wm_prog_key.tex_layout =
+      compute_msaa_layout_for_pipeline(brw, src.num_samples, src.msaa_layout);
+   wm_prog_key.rt_layout =
+      compute_msaa_layout_for_pipeline(brw, dst.num_samples, dst.msaa_layout);
 
-   /* src_interleaved and dst_interleaved indicate whether src and dst are
-    * truly interleaved.
+   /* src_layout and dst_layout indicate the true MSAA layout used by src and
+    * dst.
     */
-   wm_prog_key.src_interleaved = src_mt->msaa_is_interleaved;
-   wm_prog_key.dst_interleaved = dst_mt->msaa_is_interleaved;
+   wm_prog_key.src_layout = src_mt->msaa_layout;
+   wm_prog_key.dst_layout = dst_mt->msaa_layout;
 
    wm_prog_key.src_tiled_w = src.map_stencil_as_y_tiled;
    wm_prog_key.dst_tiled_w = dst.map_stencil_as_y_tiled;
@@ -1358,11 +1416,11 @@ brw_blorp_blit_params::brw_blorp_blit_params(struct brw_context *brw,
        * will mean that pixels are scrambled within the multisampling pattern.
        * TODO: what if this makes the coordinates too large?
        *
-       * Note: this only works if the destination surface's MSAA layout is
-       * interleaved.  If it's sliced, then we have no choice but to set up
-       * the rendering pipeline as multisampled.
+       * Note: this only works if the destination surface uses the IMS layout.
+       * If it's UMS, then we have no choice but to set up the rendering
+       * pipeline as multisampled.
        */
-      assert(dst_mt->msaa_is_interleaved);
+      assert(dst_mt->msaa_layout == INTEL_MSAA_LAYOUT_IMS);
       x0 = (x0 * 2) & ~3;
       y0 = (y0 * 2) & ~3;
       x1 = ALIGN(x1 * 2, 4);
@@ -1378,14 +1436,14 @@ brw_blorp_blit_params::brw_blorp_blit_params(struct brw_context *brw,
        * size, because the differences between W and Y tiling formats will
        * mean that pixels are scrambled within the tile.
        *
-       * Note: if the destination surface configured as an interleaved MSAA
-       * surface, then the effective tile size we need to align it to is
-       * smaller, because each pixel covers a 2x2 or a 4x2 block of samples.
+       * Note: if the destination surface configured to use IMS layout, then
+       * the effective tile size we need to align it to is smaller, because
+       * each pixel covers a 2x2 or a 4x2 block of samples.
        *
        * TODO: what if this makes the coordinates too large?
        */
       unsigned x_align = 64, y_align = 64;
-      if (dst_mt->num_samples > 0 && dst_mt->msaa_is_interleaved) {
+      if (dst_mt->msaa_layout == INTEL_MSAA_LAYOUT_IMS) {
          x_align /= (dst_mt->num_samples == 4 ? 2 : 4);
          y_align /= 2;
       }
diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c
index f742131..1a2bedb 100644
--- a/src/mesa/drivers/dri/i965/brw_tex_layout.c
+++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c
@@ -168,10 +168,16 @@ brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt)
       break;
 
    default:
-      if (mt->num_samples > 0 && !mt->msaa_is_interleaved)
+      switch (mt->msaa_layout) {
+      case INTEL_MSAA_LAYOUT_UMS:
+      case INTEL_MSAA_LAYOUT_CMS:
          brw_miptree_layout_texture_array(intel, mt);
-      else
+         break;
+      case INTEL_MSAA_LAYOUT_NONE:
+      case INTEL_MSAA_LAYOUT_IMS:
          i945_miptree_layout_2d(mt);
+         break;
+      }
       break;
    }
    DBG("%s: %dx%dx%d\n", __FUNCTION__,
diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index 26e65af..9d9ef31 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -1021,7 +1021,7 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
 				       width, height, depth,
 				       true,
                                        0 /* num_samples */,
-                                       false /* msaa_is_interleaved */);
+                                       INTEL_MSAA_LAYOUT_NONE);
 
 	 intel_miptree_copy_teximage(intel, intel_image, new_mt);
 	 intel_miptree_reference(&irb->mt, intel_image->mt);
diff --git a/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c b/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c
index d34bf53..6510421 100644
--- a/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c
@@ -397,8 +397,8 @@ gen7_update_renderbuffer_surface(struct brw_context *brw,
 			  sizeof(*surf), 32, &brw->wm.surf_offset[unit]);
    memset(surf, 0, sizeof(*surf));
 
-   /* Render targets can't use MSAA interleaved layout */
-   assert(!irb->mt->msaa_is_interleaved);
+   /* Render targets can't use IMS layout */
+   assert(irb->mt->msaa_layout != INTEL_MSAA_LAYOUT_IMS);
 
    if (irb->mt->align_h == 4)
       surf->ss0.vertical_alignment = 1;
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
index 7018c37..f97668a 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
@@ -74,7 +74,7 @@ intel_miptree_create_internal(struct intel_context *intel,
 			      GLuint depth0,
 			      bool for_region,
                               GLuint num_samples,
-                              bool msaa_is_interleaved)
+                              enum intel_msaa_layout msaa_layout)
 {
    struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1);
    int compress_byte = 0;
@@ -96,13 +96,22 @@ intel_miptree_create_internal(struct intel_context *intel,
    mt->cpp = compress_byte ? compress_byte : _mesa_get_format_bytes(mt->format);
    mt->num_samples = num_samples;
    mt->compressed = compress_byte ? 1 : 0;
-   mt->msaa_is_interleaved = msaa_is_interleaved;
+   mt->msaa_layout = msaa_layout;
    mt->refcount = 1; 
 
-   /* array_spacing_lod0 is only used for non-interleaved MSAA surfaces.
-    * TODO: can we use it elsewhere?
+   /* array_spacing_lod0 is only used for non-IMS MSAA surfaces.  TODO: can we
+    * use it elsewhere?
     */
-   mt->array_spacing_lod0 = num_samples > 0 && !msaa_is_interleaved;
+   switch (msaa_layout) {
+   case INTEL_MSAA_LAYOUT_NONE:
+   case INTEL_MSAA_LAYOUT_IMS:
+      mt->array_spacing_lod0 = false;
+      break;
+   case INTEL_MSAA_LAYOUT_UMS:
+   case INTEL_MSAA_LAYOUT_CMS:
+      mt->array_spacing_lod0 = true;
+      break;
+   }
 
    if (target == GL_TEXTURE_CUBE_MAP) {
       assert(depth0 == 1);
@@ -116,8 +125,9 @@ intel_miptree_create_internal(struct intel_context *intel,
        (intel->must_use_separate_stencil ||
 	(intel->has_separate_stencil &&
 	 intel->vtbl.is_hiz_depth_format(intel, format)))) {
-      /* MSAA stencil surfaces are always interleaved. */
-      bool msaa_is_interleaved = num_samples > 0;
+      /* MSAA stencil surfaces always use IMS layout. */
+      enum intel_msaa_layout msaa_layout =
+         num_samples > 0 ? INTEL_MSAA_LAYOUT_IMS : INTEL_MSAA_LAYOUT_NONE;
       mt->stencil_mt = intel_miptree_create(intel,
                                             mt->target,
                                             MESA_FORMAT_S8,
@@ -128,7 +138,7 @@ intel_miptree_create_internal(struct intel_context *intel,
                                             mt->depth0,
                                             true,
                                             num_samples,
-                                            msaa_is_interleaved);
+                                            msaa_layout);
       if (!mt->stencil_mt) {
 	 intel_miptree_release(&mt);
 	 return NULL;
@@ -176,7 +186,7 @@ intel_miptree_create(struct intel_context *intel,
 		     GLuint depth0,
 		     bool expect_accelerated_upload,
                      GLuint num_samples,
-                     bool msaa_is_interleaved)
+                     enum intel_msaa_layout msaa_layout)
 {
    struct intel_mipmap_tree *mt;
    uint32_t tiling = I915_TILING_NONE;
@@ -187,7 +197,7 @@ intel_miptree_create(struct intel_context *intel,
 	  (base_format == GL_DEPTH_COMPONENT ||
 	   base_format == GL_DEPTH_STENCIL_EXT))
 	 tiling = I915_TILING_Y;
-      else if (num_samples > 0) {
+      else if (msaa_layout != INTEL_MSAA_LAYOUT_NONE) {
          /* From p82 of the Sandy Bridge PRM, dw3[1] of SURFACE_STATE ("Tiled
           * Surface"):
           *
@@ -218,7 +228,7 @@ intel_miptree_create(struct intel_context *intel,
    mt = intel_miptree_create_internal(intel, target, format,
 				      first_level, last_level, width0,
 				      height0, depth0,
-				      false, num_samples, msaa_is_interleaved);
+				      false, num_samples, msaa_layout);
    /*
     * pitch == 0 || height == 0  indicates the null texture
     */
@@ -255,7 +265,7 @@ intel_miptree_create_for_region(struct intel_context *intel,
 				      0, 0,
 				      region->width, region->height, 1,
 				      true, 0 /* num_samples */,
-                                      false /* msaa_is_interleaved */);
+                                      INTEL_MSAA_LAYOUT_NONE);
    if (!mt)
       return mt;
 
@@ -265,27 +275,24 @@ intel_miptree_create_for_region(struct intel_context *intel,
 }
 
 /**
- * Determine whether the MSAA surface being created should use an interleaved
- * layout or a sliced layout, based on the chip generation and the surface
- * type.
+ * Determine which MSAA layout should be used by the MSAA surface being
+ * created, based on the chip generation and the surface type.
  */
-static bool
-msaa_format_is_interleaved(struct intel_context *intel, gl_format format)
+static enum intel_msaa_layout
+compute_msaa_layout(struct intel_context *intel, gl_format format)
 {
-   /* Prior to Gen7, all surfaces used interleaved layout. */
+   /* Prior to Gen7, all MSAA surfaces used IMS layout. */
    if (intel->gen < 7)
-      return true;
+      return INTEL_MSAA_LAYOUT_IMS;
 
-   /* In Gen7, interleaved layout is only used for depth and stencil
-    * buffers.
-    */
+   /* In Gen7, IMS layout is only used for depth and stencil buffers. */
    switch (_mesa_get_format_base_format(format)) {
    case GL_DEPTH_COMPONENT:
    case GL_STENCIL_INDEX:
    case GL_DEPTH_STENCIL:
-      return true;
+      return INTEL_MSAA_LAYOUT_IMS;
    default:
-      return false;
+      return INTEL_MSAA_LAYOUT_UMS;
    }
 }
 
@@ -298,12 +305,12 @@ intel_miptree_create_for_renderbuffer(struct intel_context *intel,
 {
    struct intel_mipmap_tree *mt;
    uint32_t depth = 1;
-   bool msaa_is_interleaved = false;
+   enum intel_msaa_layout msaa_layout = INTEL_MSAA_LAYOUT_NONE;
 
    if (num_samples > 0) {
       /* Adjust width/height/depth for MSAA */
-      msaa_is_interleaved = msaa_format_is_interleaved(intel, format);
-      if (msaa_is_interleaved) {
+      msaa_layout = compute_msaa_layout(intel, format);
+      if (msaa_layout == INTEL_MSAA_LAYOUT_IMS) {
          /* In the Sandy Bridge PRM, volume 4, part 1, page 31, it says:
           *
           *     "Any of the other messages (sample*, LOD, load4) used with a
@@ -361,7 +368,7 @@ intel_miptree_create_for_renderbuffer(struct intel_context *intel,
 
    mt = intel_miptree_create(intel, GL_TEXTURE_2D, format, 0, 0,
 			     width, height, depth, true, num_samples,
-                             msaa_is_interleaved);
+                             msaa_layout);
 
    return mt;
 }
@@ -635,8 +642,7 @@ intel_miptree_alloc_hiz(struct intel_context *intel,
                         GLuint num_samples)
 {
    assert(mt->hiz_mt == NULL);
-   /* MSAA HiZ surfaces are always interleaved. */
-   bool msaa_is_interleaved = num_samples > 0;
+   /* MSAA HiZ surfaces always use IMS layout. */
    mt->hiz_mt = intel_miptree_create(intel,
                                      mt->target,
                                      MESA_FORMAT_X8_Z24,
@@ -647,7 +653,7 @@ intel_miptree_alloc_hiz(struct intel_context *intel,
                                      mt->depth0,
                                      true,
                                      num_samples,
-                                     msaa_is_interleaved);
+                                     INTEL_MSAA_LAYOUT_IMS);
 
    if (!mt->hiz_mt)
       return false;
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
index 5c57e02..e0ed4fe 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
@@ -138,6 +138,42 @@ struct intel_mipmap_level
    } *slice;
 };
 
+/**
+ * Enum for keeping track of the different MSAA layouts supported by Gen7.
+ */
+enum intel_msaa_layout
+{
+   /**
+    * Ordinary surface with no MSAA.
+    */
+   INTEL_MSAA_LAYOUT_NONE,
+
+   /**
+    * Interleaved Multisample Surface.  The additional samples are
+    * accommodated by scaling up the width and the height of the surface so
+    * that all the samples corresponding to a pixel are located at nearby
+    * memory locations.
+    */
+   INTEL_MSAA_LAYOUT_IMS,
+
+   /**
+    * Uncompressed Multisample Surface.  The surface is stored as a 2D array,
+    * with array slice n containing all pixel data for sample n.
+    */
+   INTEL_MSAA_LAYOUT_UMS,
+
+   /**
+    * Compressed Multisample Surface.  The surface is stored as in
+    * INTEL_MSAA_LAYOUT_UMS, but there is an additional buffer called the MCS
+    * (Multisample Control Surface) buffer.  Each pixel in the MCS buffer
+    * indicates the mapping from sample number to array slice.  This allows
+    * the common case (where all samples constituting a pixel have the same
+    * color value) to be stored efficiently by just using a single array
+    * slice.
+    */
+   INTEL_MSAA_LAYOUT_CMS,
+};
+
 struct intel_mipmap_tree
 {
    /* Effectively the key:
@@ -182,15 +218,9 @@ struct intel_mipmap_tree
    bool array_spacing_lod0;
 
    /**
-    * For MSAA buffers, there are two possible layouts:
-    * - Interleaved, in which the additional samples are accommodated
-    *   by scaling up the width and height of the surface.
-    * - Sliced, in which the surface is stored as a 2D array, with
-    *   array slice n containing all pixel data for sample n.
-    *
-    * This value is true if num_samples > 0 and the format is interleaved.
+    * MSAA layout used by this buffer.
     */
-   bool msaa_is_interleaved;
+   enum intel_msaa_layout msaa_layout;
 
    /* Derived from the above:
     */
@@ -259,7 +289,7 @@ struct intel_mipmap_tree *intel_miptree_create(struct intel_context *intel,
                                                GLuint depth0,
 					       bool expect_accelerated_upload,
                                                GLuint num_samples,
-                                               bool msaa_is_interleaved);
+                                               enum intel_msaa_layout msaa_layout);
 
 struct intel_mipmap_tree *
 intel_miptree_create_for_region(struct intel_context *intel,
diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c
index 6e7e7018..1a63974 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_image.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_image.c
@@ -101,7 +101,7 @@ intel_miptree_create_for_teximage(struct intel_context *intel,
 			       depth,
 			       expect_accelerated_upload,
                                0 /* num_samples */,
-                               false /* msaa_is_interleaved */);
+                               INTEL_MSAA_LAYOUT_NONE);
 }
 
 /* There are actually quite a few combinations this will work for,
diff --git a/src/mesa/drivers/dri/intel/intel_tex_validate.c b/src/mesa/drivers/dri/intel/intel_tex_validate.c
index c2d7d67..34bbbb8 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_validate.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_validate.c
@@ -88,7 +88,7 @@ intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit)
                                           depth,
 					  true,
                                           0 /* num_samples */,
-                                          false /* msaa_is_interleaved */);
+                                          INTEL_MSAA_LAYOUT_NONE);
       if (!intelObj->mt)
          return false;
    }
-- 
1.7.7.6



More information about the mesa-dev mailing list