[Mesa-dev] [v2 18/39] intel/isl/gen6: Add offsetting support for back-to-back layouts

Topi Pohjolainen topi.pohjolainen at gmail.com
Wed May 3 09:22:31 UTC 2017


Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
---
 src/intel/blorp/blorp_blit.c      |  2 +-
 src/intel/isl/isl.c               | 29 +++++++++++++++++++++---
 src/intel/isl/isl.h               | 14 ++++++++++--
 src/intel/isl/isl_gen6.c          | 46 +++++++++++++++++++++++++++++++++++++++
 src/intel/isl/isl_storage_image.c |  3 ++-
 5 files changed, 87 insertions(+), 7 deletions(-)

diff --git a/src/intel/blorp/blorp_blit.c b/src/intel/blorp/blorp_blit.c
index 8e3fc31..ca42600 100644
--- a/src/intel/blorp/blorp_blit.c
+++ b/src/intel/blorp/blorp_blit.c
@@ -1398,7 +1398,7 @@ surf_convert_to_single_slice(const struct isl_device *isl_dev,
       layer = info->view.base_array_layer;
 
    uint32_t x_offset_sa, y_offset_sa;
-   isl_surf_get_image_offset_sa(&info->surf, info->view.base_level,
+   isl_surf_get_image_offset_sa(isl_dev, &info->surf, info->view.base_level,
                                 layer, z, &x_offset_sa, &y_offset_sa);
 
    uint32_t byte_offset;
diff --git a/src/intel/isl/isl.c b/src/intel/isl/isl.c
index f89f351..e06bb94 100644
--- a/src/intel/isl/isl.c
+++ b/src/intel/isl/isl.c
@@ -1295,6 +1295,20 @@ isl_apply_surface_padding(const struct isl_device *dev,
    }
 }
 
+/* On Gen6 hardware doesn't support mipmapping for stencil (W-tiled) and
+ * for HIZ. As workaround one places all slices back-to-back. Slices for
+ * level zero are back-to-back, followed by slices to level one, etc. This
+ * allows layered rendering once driver offsets the image to the first
+ * slice of particular level.
+ */
+static bool
+isl_surf_needs_back_to_back_layout(const struct isl_device *dev,
+                                   enum isl_tiling tiling)
+{
+   return ISL_DEV_GEN(dev) == 6 &&
+          (tiling == ISL_TILING_W || tiling == ISL_TILING_HIZ);
+}
+
 bool
 isl_surf_init_s(const struct isl_device *dev,
                 struct isl_surf *surf,
@@ -1906,7 +1920,8 @@ get_image_offset_sa_gen9_1d(const struct isl_surf *surf,
  * @invariant logical_z_offset_px < logical depth of surface at level
  */
 void
-isl_surf_get_image_offset_sa(const struct isl_surf *surf,
+isl_surf_get_image_offset_sa(const struct isl_device *dev,
+                             const struct isl_surf *surf,
                              uint32_t level,
                              uint32_t logical_array_layer,
                              uint32_t logical_z_offset_px,
@@ -1918,6 +1933,13 @@ isl_surf_get_image_offset_sa(const struct isl_surf *surf,
    assert(logical_z_offset_px
           < isl_minify(surf->logical_level0_px.depth, level));
 
+   if (isl_surf_needs_back_to_back_layout(dev, surf->tiling)) {
+      get_image_offset_sa_gen6_back_to_back(surf, level, logical_array_layer,
+                                            logical_z_offset_px,
+                                            x_offset_sa, y_offset_sa);
+      return;
+   }
+
    switch (surf->dim_layout) {
    case ISL_DIM_LAYOUT_GEN9_1D:
       get_image_offset_sa_gen9_1d(surf, level, logical_array_layer,
@@ -1939,7 +1961,8 @@ isl_surf_get_image_offset_sa(const struct isl_surf *surf,
 }
 
 void
-isl_surf_get_image_offset_el(const struct isl_surf *surf,
+isl_surf_get_image_offset_el(const struct isl_device *dev,
+                             const struct isl_surf *surf,
                              uint32_t level,
                              uint32_t logical_array_layer,
                              uint32_t logical_z_offset_px,
@@ -1954,7 +1977,7 @@ isl_surf_get_image_offset_el(const struct isl_surf *surf,
           < isl_minify(surf->logical_level0_px.depth, level));
 
    uint32_t x_offset_sa, y_offset_sa;
-   isl_surf_get_image_offset_sa(surf, level,
+   isl_surf_get_image_offset_sa(dev, surf, level,
                                 logical_array_layer,
                                 logical_z_offset_px,
                                 &x_offset_sa,
diff --git a/src/intel/isl/isl.h b/src/intel/isl/isl.h
index 7778551..3685ddf 100644
--- a/src/intel/isl/isl.h
+++ b/src/intel/isl/isl.h
@@ -1484,6 +1484,14 @@ isl_surf_get_array_pitch(const struct isl_surf *surf)
    return isl_surf_get_array_pitch_sa_rows(surf) * surf->row_pitch;
 }
 
+void
+get_image_offset_sa_gen6_back_to_back(const struct isl_surf *surf,
+                                      uint32_t level,
+                                      uint32_t logical_array_layer,
+                                      uint32_t logical_z_offset_px,
+                                      uint32_t *x_offset_sa,
+                                      uint32_t *y_offset_sa);
+
 /**
  * Calculate the offset, in units of surface samples, to a subimage in the
  * surface.
@@ -1493,7 +1501,8 @@ isl_surf_get_array_pitch(const struct isl_surf *surf)
  * @invariant logical_z_offset_px < logical depth of surface at level
  */
 void
-isl_surf_get_image_offset_sa(const struct isl_surf *surf,
+isl_surf_get_image_offset_sa(const struct isl_device *dev,
+                             const struct isl_surf *surf,
                              uint32_t level,
                              uint32_t logical_array_layer,
                              uint32_t logical_z_offset_px,
@@ -1509,7 +1518,8 @@ isl_surf_get_image_offset_sa(const struct isl_surf *surf,
  * @invariant logical_z_offset_px < logical depth of surface at level
  */
 void
-isl_surf_get_image_offset_el(const struct isl_surf *surf,
+isl_surf_get_image_offset_el(const struct isl_device *dev,
+                             const struct isl_surf *surf,
                              uint32_t level,
                              uint32_t logical_array_layer,
                              uint32_t logical_z_offset_px,
diff --git a/src/intel/isl/isl_gen6.c b/src/intel/isl/isl_gen6.c
index b746903..8bd5dbc 100644
--- a/src/intel/isl/isl_gen6.c
+++ b/src/intel/isl/isl_gen6.c
@@ -145,3 +145,49 @@ isl_gen6_choose_image_alignment_el(const struct isl_device *dev,
 
    *image_align_el = isl_extent3d(4, 2, 1);
 }
+
+void
+get_image_offset_sa_gen6_back_to_back(const struct isl_surf *surf,
+                                      uint32_t level,
+                                      uint32_t logical_array_layer,
+                                      uint32_t logical_z_offset_px,
+                                      uint32_t *x_offset_sa,
+                                      uint32_t *y_offset_sa)
+{
+   assert(level < surf->levels);
+
+   const struct isl_extent3d image_align_sa =
+      isl_surf_get_image_alignment_sa(surf);
+
+   assert(surf->tiling == ISL_TILING_W ||
+          surf->tiling == ISL_TILING_HIZ); 
+   const uint32_t tile_align_h = surf->tiling == ISL_TILING_W ? 64 : 32;
+
+   uint32_t y = 0;
+   for (unsigned i = 0; i < level; ++i) {
+      const unsigned d = surf->dim_layout == ISL_DIM_LAYOUT_GEN4_3D ?
+                         isl_minify(surf->phys_level0_sa.depth, i) :
+                         surf->phys_level0_sa.array_len;
+      const unsigned h = isl_minify(surf->phys_level0_sa.height, i);
+      y += d * isl_align_npot(h, image_align_sa.h);
+
+      /* Align on tile boundary so that driver can offset without intra-tile
+       * offsets.
+       */
+      y = isl_align(y, tile_align_h);
+   }
+
+   const unsigned level_h = isl_minify(surf->phys_level0_sa.height, level);
+   const unsigned aligned_level_h = isl_align_npot(level_h, image_align_sa.h);
+
+   if (surf->dim_layout == ISL_DIM_LAYOUT_GEN4_3D) {
+      assert(logical_z_offset_px < surf->logical_level0_px.depth);
+      y += logical_z_offset_px * aligned_level_h;
+   } else {
+      assert(logical_array_layer < surf->logical_level0_px.array_len);
+      y += logical_array_layer * aligned_level_h;
+   }
+
+   *x_offset_sa = 0;
+   *y_offset_sa = y;
+}
diff --git a/src/intel/isl/isl_storage_image.c b/src/intel/isl/isl_storage_image.c
index 4c56e78..9aeeede 100644
--- a/src/intel/isl/isl_storage_image.c
+++ b/src/intel/isl/isl_storage_image.c
@@ -226,7 +226,8 @@ isl_surf_fill_image_param(const struct isl_device *dev,
                        view->base_array_layer;
    }
 
-   isl_surf_get_image_offset_el(surf, view->base_level, view->base_array_layer,
+   isl_surf_get_image_offset_el(dev, surf,
+                                view->base_level, view->base_array_layer,
                                 0, &param->offset[0],  &param->offset[1]);
 
    const int cpp = isl_format_get_layout(surf->format)->bpb / 8;
-- 
2.9.3



More information about the mesa-dev mailing list