[Mesa-dev] [PATCH 22/26] i965: Add non-msrt mcs array/mipmap alignment restrictions

Topi Pohjolainen topi.pohjolainen at gmail.com
Tue Oct 11 19:26:54 UTC 2016


There are actually two contradicting pieces in the bspec:

>From the BSpec: 3D-Media-GPGPU Engine - 3D Pipeline Stages - Pixel -
Pixel Backend [IVB+] - MCS Buffer for Render Target(s)

BDW:  Mip-mapped and arrayed surfaces are supported with MCS buffer
      layout with these alignments in the RT space:
      Horizontal Alignment = 256 and Vertical Alignment = 128.
SKL+: Mip-mapped and arrayed surfaces are supported with MCS buffer
      layout with these alignments in the RT space: Horizontal
      Alignment = 128 and Vertical Alignment = 64.

and

>From the BSpec: GT - Shared Functions - vol5c Shared Functions -
RENDER_SURFACE_STATE [BDW+] Issues Info 2:

PRE-SKL
For non-multisampled render target's auxiliary surface, MCS, QPitch
must be computed with Horizontal Alignment = 256 and Surface Vertical
Alignment = 128. These alignments are only for MCS buffer and not for
associated render target.

SKL+
For non-multisampled render target's CCS auxiliary surface, QPitch
must be computed with Horizontal Alignment = 128 and Surface Vertical
Alignment = 256. These alignments are only for CCS buffer and not for
associated render target.

The former seems to hold for individual mip-levels and the latter
for qpitch.

Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
---
 src/mesa/drivers/dri/i965/brw_tex_layout.c       | 68 +++++++++++++++++++-----
 src/mesa/drivers/dri/i965/brw_wm_surface_state.c |  2 +-
 src/mesa/drivers/dri/i965/intel_mipmap_tree.c    | 31 ++++++++++-
 src/mesa/drivers/dri/i965/intel_mipmap_tree.h    |  4 +-
 4 files changed, 89 insertions(+), 16 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c
index 94ded33..9c28500 100644
--- a/src/mesa/drivers/dri/i965/brw_tex_layout.c
+++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c
@@ -199,8 +199,24 @@ tr_mode_vertical_texture_alignment(const struct intel_mipmap_tree *mt)
 
 static unsigned int
 intel_vertical_texture_alignment_unit(struct brw_context *brw,
-                                      const struct intel_mipmap_tree *mt)
+                                      const struct intel_mipmap_tree *mt,
+                                      uint32_t layout_flags)
 {
+   /* From the BSpec: 3D-Media-GPGPU Engine - 3D Pipeline Stages - Pixel -
+    * Pixel Backend [IVB+] - MCS Buffer for Render Target(s)
+    *
+    * BDW:  Mip-mapped and arrayed surfaces are supported with MCS buffer
+    *       layout with these alignments in the RT space:
+    *       Horizontal Alignment = 256 and Vertical Alignment = 128.
+    * SKL+: Mip-mapped and arrayed surfaces are supported with MCS buffer
+    *       layout with these alignments in the RT space: Horizontal
+    *       Alignment = 128 and Vertical Alignment = 64.
+    */
+   if (brw->gen >= 8 && mt->num_samples <= 1 &&
+       layout_flags & MIPTREE_LAYOUT_FOR_MCS) {
+      return brw->gen == 8 ? 128 : 64;
+   }
+
    /**
     * +----------------------------------------------------------------------+
     * |                                        | alignment unit height ("j") |
@@ -380,7 +396,7 @@ brw_miptree_get_horizontal_slice_pitch(const struct brw_context *brw,
 unsigned
 brw_miptree_get_vertical_slice_pitch(const struct brw_context *brw,
                                      const struct intel_mipmap_tree *mt,
-                                     unsigned level)
+                                     unsigned level, uint32_t layout_flags)
 {
    unsigned qpitch;
 
@@ -420,6 +436,26 @@ brw_miptree_get_vertical_slice_pitch(const struct brw_context *brw,
       qpitch = h0 + h1 + (brw->gen >= 7 ? 12 : 11) * mt->valign;
    }
 
+   /* From the BSpec: GT - Shared Functions - vol5c Shared Functions -
+    * RENDER_SURFACE_STATE [BDW+] Issues Info 2:
+    *
+    * PRE-SKL
+    * For non-multisampled render target's auxiliary surface, MCS, QPitch
+    * must be computed with Horizontal Alignment = 256 and Surface Vertical
+    * Alignment = 128. These alignments are only for MCS buffer and not for
+    * associated render target.
+    *
+    * SKL+
+    * For non-multisampled render target's CCS auxiliary surface, QPitch
+    * must be computed with Horizontal Alignment = 128 and Surface Vertical
+    * Alignment = 256. These alignments are only for CCS buffer and not for
+    * associated render target.
+    */
+   if (brw->gen >= 8 && (layout_flags & MIPTREE_LAYOUT_FOR_MCS) &&
+       (mt->last_level || mt->logical_depth0 > 1)) {
+      qpitch = ALIGN(qpitch, brw->gen == 8 ? 128 : 256);
+   }
+
    return qpitch;
 }
 
@@ -459,7 +495,8 @@ gen9_use_linear_1d_layout(const struct brw_context *brw,
 
 static void
 brw_miptree_layout_texture_array(struct brw_context *brw,
-				 struct intel_mipmap_tree *mt)
+                                 struct intel_mipmap_tree *mt,
+                                 uint32_t layout_flags)
 {
    unsigned height = mt->physical_height0;
    bool layout_1d = gen9_use_linear_1d_layout(brw, mt);
@@ -479,7 +516,9 @@ brw_miptree_layout_texture_array(struct brw_context *brw,
        */
       mt->qpitch = mt->total_width;
    } else {
-      mt->qpitch = brw_miptree_get_vertical_slice_pitch(brw, mt, 0);
+      mt->qpitch = brw_miptree_get_vertical_slice_pitch(brw, mt, 0,
+                                                        layout_flags);
+
       /* Unlike previous generations the qpitch is a multiple of the
        * compressed block size on Gen9 so physical_qpitch matches mt->qpitch.
        */
@@ -653,7 +692,8 @@ brw_miptree_choose_tiling(struct brw_context *brw,
 
 static void
 intel_miptree_set_total_width_height(struct brw_context *brw,
-                                     struct intel_mipmap_tree *mt)
+                                     struct intel_mipmap_tree *mt,
+                                     uint32_t layout_flags)
 {
    switch (mt->target) {
    case GL_TEXTURE_CUBE_MAP:
@@ -663,29 +703,30 @@ intel_miptree_set_total_width_height(struct brw_context *brw,
          brw_miptree_layout_texture_3d(brw, mt);
       } else {
          /* All other hardware stores cube maps as 2D arrays. */
-	 brw_miptree_layout_texture_array(brw, mt);
+         brw_miptree_layout_texture_array(brw, mt, layout_flags);
       }
       break;
 
    case GL_TEXTURE_3D:
-      if (brw->gen >= 9)
-         brw_miptree_layout_texture_array(brw, mt);
-      else
+      if (brw->gen >= 9) {
+         brw_miptree_layout_texture_array(brw, mt, layout_flags);
+      } else {
          brw_miptree_layout_texture_3d(brw, mt);
+      }
       break;
 
    case GL_TEXTURE_1D_ARRAY:
    case GL_TEXTURE_2D_ARRAY:
    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
    case GL_TEXTURE_CUBE_MAP_ARRAY:
-      brw_miptree_layout_texture_array(brw, mt);
+      brw_miptree_layout_texture_array(brw, mt, layout_flags);
       break;
 
    default:
       switch (mt->msaa_layout) {
       case INTEL_MSAA_LAYOUT_UMS:
       case INTEL_MSAA_LAYOUT_CMS:
-         brw_miptree_layout_texture_array(brw, mt);
+         brw_miptree_layout_texture_array(brw, mt, layout_flags);
          break;
       case INTEL_MSAA_LAYOUT_NONE:
       case INTEL_MSAA_LAYOUT_IMS:
@@ -769,7 +810,8 @@ intel_miptree_set_alignment(struct brw_context *brw,
    } else {
       mt->halign =
          intel_horizontal_texture_alignment_unit(brw, mt, layout_flags);
-      mt->valign = intel_vertical_texture_alignment_unit(brw, mt);
+      mt->valign = intel_vertical_texture_alignment_unit(brw, mt,
+                                                         layout_flags);
    }
 }
 
@@ -781,7 +823,7 @@ brw_miptree_layout(struct brw_context *brw,
    mt->tr_mode = INTEL_MIPTREE_TRMODE_NONE;
 
    intel_miptree_set_alignment(brw, mt, layout_flags);
-   intel_miptree_set_total_width_height(brw, mt);
+   intel_miptree_set_total_width_height(brw, mt, layout_flags);
 
    if (!mt->total_width || !mt->total_height) {
       intel_miptree_release(&mt);
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 7ee9486..482a034 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -1669,7 +1669,7 @@ update_texture_image_param(struct brw_context *brw,
    param->stride[2] =
       brw_miptree_get_horizontal_slice_pitch(brw, mt, u->Level);
    param->stride[3] =
-      brw_miptree_get_vertical_slice_pitch(brw, mt, u->Level);
+      brw_miptree_get_vertical_slice_pitch(brw, mt, u->Level, 0);
 
    if (mt->tiling == I915_TILING_X) {
       /* An X tile is a rectangular block of 512x8 bytes. */
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
index 0fed0ee..f51392f 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
@@ -1624,7 +1624,8 @@ intel_miptree_alloc_non_msrt_mcs(struct brw_context *brw,
    uint32_t layout_flags = MIPTREE_LAYOUT_TILING_Y;
 
    if (brw->gen >= 8) {
-      layout_flags |= MIPTREE_LAYOUT_FORCE_HALIGN16;
+      layout_flags |= (MIPTREE_LAYOUT_FORCE_HALIGN16 |
+                       MIPTREE_LAYOUT_FOR_MCS);
    }
 
    /* In case of compression mcs buffer needs to be initialised requiring the
@@ -1664,6 +1665,34 @@ intel_miptree_alloc_non_msrt_mcs(struct brw_context *brw,
       mt->msaa_layout = INTEL_MSAA_LAYOUT_CMS;
    }
 
+   /* From the BSpec: GT - Shared Functions - vol5c Shared Functions -
+    * RENDER_SURFACE_STATE [BDW+] Issues Info 2:
+    *
+    * PRE-SKL
+    * For non-multisampled render target's auxiliary surface, MCS, QPitch
+    * must be computed with Horizontal Alignment = 256 and Surface Vertical
+    * Alignment = 128. These alignments are only for MCS buffer and not for
+    * associated render target.
+    *
+    * SKL+
+    * For non-multisampled render target's CCS auxiliary surface, QPitch
+    * must be computed with Horizontal Alignment = 128 and Surface Vertical
+    * Alignment = 256. These alignments are only for CCS buffer and not for
+    * associated render target.
+    */
+   if ((mt->last_level || mt->logical_depth0 > 1)) {
+      if (brw->gen >= 9) {
+         assert(mt->pitch % 128 == 0);
+      } else if (brw->gen == 8) {
+         /* TODO: In practise, alignment of 256 causes hangs - fall back to
+          * 128.
+          */
+         assert(mt->pitch % 128 == 0);
+      } else {
+         unreachable("mipmapped or/and arrayed are only supported for gen8+");
+      }
+   }
+
    return mt->mcs_mt;
 }
 
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
index 079fb4a..1ba2fb9 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
@@ -667,6 +667,8 @@ enum {
                                              MIPTREE_LAYOUT_TILING_NONE,
 
    MIPTREE_LAYOUT_FOR_SCANOUT              = 1 << 7,
+
+   MIPTREE_LAYOUT_FOR_MCS                  = 1 << 8,
 };
 
 struct intel_mipmap_tree *intel_miptree_create(struct brw_context *brw,
@@ -964,7 +966,7 @@ brw_miptree_get_horizontal_slice_pitch(const struct brw_context *brw,
 unsigned
 brw_miptree_get_vertical_slice_pitch(const struct brw_context *brw,
                                      const struct intel_mipmap_tree *mt,
-                                     unsigned level);
+                                     unsigned level, uint32_t layout_flags);
 
 void
 brw_miptree_layout(struct brw_context *brw,
-- 
2.5.5



More information about the mesa-dev mailing list