[Mesa-dev] [v3 19/19] i965/gen6: Represent mipmapped stencil with isl_surf array

Topi Pohjolainen topi.pohjolainen at gmail.com
Mon May 15 12:08:09 UTC 2017


This is only compile tested!!

Alternatively one could keep gen6_back_to_back_minify() and
gen6_back_to_back_offset() (which in turn relies on
gen6_back_to_back_total_height()) and make the loop in
make_gen6_stencil_surface() a little simpler.

I don't personally like this too much:

1) Precomputed isl surfaces are only needed for one purpose: blorp
   surface setup. Stencil state setup and mapping only need the
   offset.

2) In my opinion both offset and isl surf per level can be
   calculated that easily on-demand that the precomputed table to
   be justified.

3) Users (blorp surface setup, offsetting, mapping and stencil
   buffer setup) don't really become any simpler.

4) Having ISL surface per level still requires some overrides
   (row_pitch) that I was expecting it would solve compared to
   using one surface only.

CC: Chad Versace <chadversary at chromium.org>
CC: Jason Ekstrand <jason at jlekstrand.net>
CC: Nanley Chery <nanley.g.chery at intel.com>
Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
---
 src/mesa/drivers/dri/i965/brw_blorp.c         |  13 +--
 src/mesa/drivers/dri/i965/brw_tex_layout.c    |  77 -------------
 src/mesa/drivers/dri/i965/gen6_depth_state.c  |  15 ++-
 src/mesa/drivers/dri/i965/intel_mipmap_tree.c | 158 ++++++++++++++++++++------
 src/mesa/drivers/dri/i965/intel_mipmap_tree.h |  25 ++--
 5 files changed, 150 insertions(+), 138 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_blorp.c b/src/mesa/drivers/dri/i965/brw_blorp.c
index 7c2f7b5..4d98171 100644
--- a/src/mesa/drivers/dri/i965/brw_blorp.c
+++ b/src/mesa/drivers/dri/i965/brw_blorp.c
@@ -161,7 +161,6 @@ blorp_surf_for_miptree(struct brw_context *brw,
          intel_miptree_check_level_layer(mt, *level, start_layer + i);
    }
 
-   surf->surf = &tmp_surfs[0];
    surf->addr = (struct blorp_address) {
       .buffer = mt->bo,
       .offset = mt->offset,
@@ -171,7 +170,7 @@ blorp_surf_for_miptree(struct brw_context *brw,
    };
 
    if (brw->gen == 6 && mt->format == MESA_FORMAT_S_UINT8) {
-      assert(mt->array_layout == GEN6_BACK_TO_BACK);
+      assert(*level < mt->gen6_stencil_surf.num_levels);
 
       /* Sandy bridge stencil and HiZ use this ALL_SLICES_AT_EACH_LOD hack in
        * order to allow for layered rendering.  The hack makes each LOD of the
@@ -183,20 +182,20 @@ blorp_surf_for_miptree(struct brw_context *brw,
        *
        * See also gen6_depth_stencil_state.c
        */
-      uint32_t x_offset_sa, y_offset_sa;
-      gen6_back_to_back_offset(&mt->surf, *level, 0,
-                               &x_offset_sa, &y_offset_sa);
+      uint32_t x_offset_sa = mt->gen6_stencil_surf.levels[*level].x_offset;
+      uint32_t y_offset_sa = mt->gen6_stencil_surf.levels[*level].y_offset;
+
       assert(x_offset_sa == 0);
 
       /* Pitch represents two rows interleaved. */
       const uint32_t offset = y_offset_sa * mt->surf.row_pitch / 2;
 
       surf->addr.offset += offset;
-
-      tmp_surfs[0] = gen6_back_to_back_minify(&mt->surf, *level);
+      surf->surf = &mt->gen6_stencil_surf.levels[*level].surf;
 
       *level = 0;
    } else {
+      surf->surf = &tmp_surfs[0];
       intel_miptree_get_isl_surf(brw, mt, &tmp_surfs[0]);
    }
 
diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c
index 3fbc9cf..b04f394 100644
--- a/src/mesa/drivers/dri/i965/brw_tex_layout.c
+++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c
@@ -662,80 +662,3 @@ brw_miptree_layout(struct brw_context *brw,
 
    return true;
 }
-
-/* Provide surface representing selected single level. */
-struct isl_surf
-gen6_back_to_back_minify(const struct isl_surf *surf, unsigned levels)
-{
-   struct isl_surf s = *surf;
-
-   s.logical_level0_px = isl_extent4d_minify(&surf->logical_level0_px,
-                                             surf->dim, levels);
-   s.phys_level0_sa = isl_extent4d_minify(&surf->phys_level0_sa,
-                                          surf->dim, levels);
-   s.levels = 1;
-
-   const struct isl_extent3d image_align_sa =
-      isl_surf_get_image_alignment_sa(surf);
-   const unsigned d = s.dim == ISL_SURF_DIM_3D ?
-      s.phys_level0_sa.depth : s.phys_level0_sa.array_len;
-   const unsigned aligned_h =
-      isl_align_npot(s.phys_level0_sa.height, image_align_sa.h);
-
-   const uint32_t tile_align_h = surf->tiling == ISL_TILING_W ? 64 : 32;
-   s.size = ALIGN(d * aligned_h, tile_align_h) * s.row_pitch;
-
-   return s;
-}
-
-uint32_t
-gen6_back_to_back_total_height(const struct isl_extent4d *phys_level0_sa,
-                               const struct isl_extent3d *image_align_sa,
-                               enum isl_surf_dim dim,
-                               enum isl_tiling tiling, uint32_t levels)
-{
-   assert(tiling == ISL_TILING_W ||
-          tiling == ISL_TILING_HIZ); 
-   const uint32_t tile_align_h = tiling == ISL_TILING_W ? 64 : 32;
-
-   uint32_t total_h = 0;
-   for (unsigned i = 0; i < levels; ++i) {
-      const unsigned d = dim == ISL_SURF_DIM_3D ?
-         isl_minify(phys_level0_sa->depth, i) : phys_level0_sa->array_len;
-      const unsigned h = isl_minify(phys_level0_sa->height, i);
-      total_h += d * isl_align_npot(h, image_align_sa->h);
-
-      /* Align on tile boundary so that driver can offset without intra-tile
-       * offsets.
-       */
-      total_h = isl_align(total_h, tile_align_h);
-   }
-
-   return total_h;
-}
-
-void
-gen6_back_to_back_offset(const struct isl_surf *surf,
-                         uint32_t level, uint32_t layer,
-                         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);
-   const uint32_t y = gen6_back_to_back_total_height(&surf->phys_level0_sa,
-                                                     &image_align_sa,
-                                                     surf->dim, surf->tiling,
-                                                     level);
-
-   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 == ISL_SURF_DIM_3D)
-      assert(layer < surf->logical_level0_px.depth);
-   else
-      assert(layer < surf->logical_level0_px.array_len);
-
-   *x_offset_sa = 0;
-   *y_offset_sa = y + layer * aligned_level_h;
-}
diff --git a/src/mesa/drivers/dri/i965/gen6_depth_state.c b/src/mesa/drivers/dri/i965/gen6_depth_state.c
index 36d92f0..4166b47 100644
--- a/src/mesa/drivers/dri/i965/gen6_depth_state.c
+++ b/src/mesa/drivers/dri/i965/gen6_depth_state.c
@@ -188,19 +188,22 @@ gen6_emit_depth_stencil_hiz(struct brw_context *brw,
 
       /* Emit stencil buffer. */
       if (separate_stencil) {
-         assert(stencil_mt->surf.size > 0);
+         const struct gen6_stencil_level *level =
+            &mt->gen6_stencil_surf.levels[lod];
+
+         assert(lod < mt->gen6_stencil_surf.num_levels);
+
+         uint32_t x_offset_sa = level->x_offset;
+         uint32_t y_offset_sa = level->y_offset;
 
-         uint32_t x_offset_sa, y_offset_sa;
-         gen6_back_to_back_offset(&stencil_mt->surf, lod, 0,
-                                  &x_offset_sa, &y_offset_sa);
          assert(x_offset_sa == 0);
          
          /* Pitch represents two rows interleaved. */
-         const uint32_t offset = y_offset_sa * stencil_mt->surf.row_pitch / 2;
+         const uint32_t offset = y_offset_sa * level->surf.row_pitch / 2;
 
 	 BEGIN_BATCH(3);
 	 OUT_BATCH((_3DSTATE_STENCIL_BUFFER << 16) | (3 - 2));
-	 OUT_BATCH(stencil_mt->surf.row_pitch - 1);
+	 OUT_BATCH(level->surf.row_pitch - 1);
 	 OUT_RELOC(stencil_mt->bo,
 		   I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
 		   offset);
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
index 4721d22..955061d 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
@@ -602,24 +602,6 @@ intel_lower_compressed_format(struct brw_context *brw, mesa_format format)
    }
 }
 
-static void
-gen6_stencil_override(struct isl_surf *surf, unsigned levels)
-{
-   surf->levels = levels;
-
-   const struct isl_extent3d image_align_sa =
-      isl_surf_get_image_alignment_sa(surf);
-   const uint32_t total_h = gen6_back_to_back_total_height(
-                                &surf->phys_level0_sa, &image_align_sa,
-                                surf->dim, surf->tiling, surf->levels);
-
-   /* Pitch represents two rows interleaved. */
-   surf->size = total_h * surf->row_pitch / 2;
-
-   /* There is no such thing with back-to-back layout. */
-   surf->array_pitch_el_rows = 0;
-}
-
 static struct intel_mipmap_tree *
 make_surface(struct brw_context *brw, GLenum target, mesa_format format,
              unsigned first_level, unsigned last_level,
@@ -648,16 +630,13 @@ make_surface(struct brw_context *brw, GLenum target, mesa_format format,
        num_samples, width0, height0, depth0,
        first_level, last_level, mt);
 
-   const bool is_gen6_stencil = brw->gen == 6 &&
-                                format == MESA_FORMAT_S_UINT8;
-
    struct isl_surf_init_info init_info = {
       .dim = get_isl_surf_dim(target),
       .format = translate_tex_format(brw, format, false),
       .width = width0,
       .height = height0,
       .depth = target == GL_TEXTURE_3D ? depth0 : 1,
-      .levels = is_gen6_stencil ? 1 : last_level + 1,
+      .levels = last_level + 1,
       .array_len = target == GL_TEXTURE_3D ? 1 : depth0,
       .samples = MAX2(num_samples, 1),
       .usage = isl_usage_flags, 
@@ -667,11 +646,6 @@ make_surface(struct brw_context *brw, GLenum target, mesa_format format,
    if (!isl_surf_init_s(&brw->isl_dev, &mt->surf, &init_info))
       goto fail;
 
-   if (is_gen6_stencil) {
-      mt->array_layout = GEN6_BACK_TO_BACK;
-      gen6_stencil_override(&mt->surf, last_level + 1);
-   }
-
    assert(mt->surf.size % mt->surf.row_pitch == 0);
 
    unsigned pitch = mt->surf.row_pitch;
@@ -700,6 +674,117 @@ fail:
 }
 
 static struct intel_mipmap_tree *
+make_gen6_stencil_surface(struct brw_context *brw,
+                          GLenum target, mesa_format format,
+                          unsigned first_level, unsigned last_level,
+                          unsigned width0, unsigned height0, unsigned depth0,
+                          unsigned num_samples, enum isl_tiling isl_tiling,
+                          isl_surf_usage_flags_t isl_usage_flags,
+                          uint32_t alloc_flags)
+{
+   struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1);
+   if (!mt)
+      return NULL;
+
+   mt->gen6_stencil_surf.levels = calloc(sizeof(struct gen6_stencil_level),
+                                         last_level + 1);
+   if (!mt->gen6_stencil_surf.levels) {
+      free(mt);
+      return NULL;
+   }
+
+   if (!create_mapping_table(target, first_level, last_level, depth0,
+                             mt->level)) {
+      free(mt->gen6_stencil_surf.levels);
+      free(mt);
+      return NULL;
+   }
+
+   if (target == GL_TEXTURE_CUBE_MAP ||
+       target == GL_TEXTURE_CUBE_MAP_ARRAY)
+      isl_usage_flags |= ISL_SURF_USAGE_CUBE_BIT;
+
+   DBG("%s: %s %s %ux %u:%u:%u %d..%d <-- %p\n",
+        __func__,
+       _mesa_enum_to_string(target),
+       _mesa_get_format_name(format),
+       num_samples, width0, height0, depth0,
+       first_level, last_level, mt);
+
+   unsigned curr_y = 0;
+   for (unsigned level = 0; level <= last_level; level++) {
+      struct isl_surf_init_info init_info = {
+         .dim = get_isl_surf_dim(target),
+         .format = translate_tex_format(brw, format, false),
+         .width = minify(width0, level),
+         .height = minify(height0, level),
+         .depth = target == GL_TEXTURE_3D ? minify(depth0, level) : 1,
+         .levels = 1,
+         .array_len = target == GL_TEXTURE_3D ? 1 : depth0,
+         .samples = MAX2(num_samples, 1),
+         .usage = isl_usage_flags, 
+         .tiling_flags = 1u << isl_tiling
+      };
+
+      struct gen6_stencil_level *curr_level =
+         &mt->gen6_stencil_surf.levels[level];
+
+      if (!isl_surf_init_s(&brw->isl_dev, &curr_level->surf, &init_info)) {
+         intel_miptree_release(&mt);
+         return NULL;
+      }
+
+      curr_level->x_offset = 0;
+      curr_level->y_offset = curr_y;
+
+      const unsigned curr_h = minify(height0, level);
+      const unsigned curr_d = curr_level->surf.dim == ISL_SURF_DIM_3D ?
+         minify(depth0, level) : depth0;
+
+      const struct isl_extent3d image_align_sa =
+         isl_surf_get_image_alignment_sa(&curr_level->surf);
+
+      const unsigned curr_total_h =
+         curr_d * ALIGN_NPOT(curr_h, image_align_sa.h);
+
+      /* Override row_pitch to what is mandated by level zero, and then
+       * size accordingly.
+       */
+      if (level) {
+         curr_level->surf.row_pitch =
+            mt->gen6_stencil_surf.levels[0].surf.row_pitch;
+         curr_level->surf.size = curr_total_h * curr_level->surf.row_pitch;
+      }
+
+      curr_y += curr_total_h;
+   }
+
+   mt->gen6_stencil_surf.num_levels = last_level + 1;
+
+   unsigned pitch = mt->gen6_stencil_surf.levels[0].surf.row_pitch;
+   mt->bo = brw_bo_alloc_tiled(brw->bufmgr, "isl-miptree",
+                               mt->gen6_stencil_surf.levels[0].surf.row_pitch,
+                               curr_y,
+                               1, isl_tiling_to_bufmgr_tiling(isl_tiling),
+                               &pitch, alloc_flags);
+   if (!mt->bo) {
+      intel_miptree_release(&mt);
+      return NULL;
+   }
+
+   assert(pitch == mt->gen6_stencil_surf.levels[0].surf.row_pitch);
+
+   mt->target = target;
+   mt->format = format;
+   mt->refcount = 1;
+
+   exec_list_make_empty(&mt->hiz_map);
+   exec_list_make_empty(&mt->color_resolve_map);
+
+   return mt;
+}
+
+static struct intel_mipmap_tree *
 miptree_create(struct brw_context *brw,
                GLenum target,
                mesa_format format,
@@ -712,11 +797,13 @@ miptree_create(struct brw_context *brw,
                uint32_t layout_flags)
 {
    if (brw->gen == 6 && format == MESA_FORMAT_S_UINT8)
-      return make_surface(brw, target, format, first_level, last_level,
-                          width0, height0, depth0, num_samples, ISL_TILING_W,
-                          ISL_SURF_USAGE_STENCIL_BIT |
-                          ISL_SURF_USAGE_TEXTURE_BIT,
-                          BO_ALLOC_FOR_RENDER);
+      return make_gen6_stencil_surface(brw, target, format,
+                                       first_level, last_level,
+                                       width0, height0, depth0, num_samples,
+                                       ISL_TILING_W,
+                                       ISL_SURF_USAGE_STENCIL_BIT |
+                                       ISL_SURF_USAGE_TEXTURE_BIT,
+                                       BO_ALLOC_FOR_RENDER);
 
    struct intel_mipmap_tree *mt;
    mesa_format tex_format = format;
@@ -1074,6 +1161,8 @@ intel_miptree_release(struct intel_mipmap_tree **mt)
 	 free((*mt)->level[i].slice);
       }
 
+      free((*mt)->gen6_stencil_surf.levels);
+
       free(*mt);
    }
    *mt = NULL;
@@ -1238,9 +1327,10 @@ intel_miptree_get_image_offset(const struct intel_mipmap_tree *mt,
       uint32_t x_offset_sa, y_offset_sa;
 
       if (mt->array_layout == GEN6_BACK_TO_BACK) {
-         gen6_back_to_back_offset(&mt->surf, level, slice,
-                                  &x_offset_sa, &y_offset_sa);
+         assert(level < mt->gen6_stencil_surf.num_levels);
 
+         x_offset_sa = mt->gen6_stencil_surf.levels[level].x_offset;
+         y_offset_sa = mt->gen6_stencil_surf.levels[level].y_offset;
       } else {
          const unsigned z = mt->surf.dim == ISL_SURF_DIM_3D ? slice : 0;
          slice = mt->surf.dim == ISL_SURF_DIM_3D ? 0 : slice;
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
index 691ff2c..c9f3261 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
@@ -354,10 +354,21 @@ struct intel_miptree_hiz_buffer
    struct intel_mipmap_tree *mt;
 };
 
+struct gen6_stencil_level {
+   struct isl_surf surf;
+   uint32_t x_offset;
+   uint32_t y_offset;
+};
+
 struct intel_mipmap_tree
 {
    struct isl_surf surf;
 
+   struct {
+      struct gen6_stencil_level *levels;
+      unsigned num_levels;
+   } gen6_stencil_surf;
+
    /**
     * Buffer object containing the surface.
     *
@@ -1035,20 +1046,6 @@ bool
 intel_miptree_sample_with_hiz(struct brw_context *brw,
                               struct intel_mipmap_tree *mt);
 
-struct isl_surf
-gen6_back_to_back_minify(const struct isl_surf *surf, unsigned levels);
-
-uint32_t
-gen6_back_to_back_total_height(const struct isl_extent4d *phys_level0_sa,
-                               const struct isl_extent3d *image_align_sa,
-                               enum isl_surf_dim dim,
-                               enum isl_tiling tiling, uint32_t levels);
-
-void
-gen6_back_to_back_offset(const struct isl_surf *surf,
-                         uint32_t level, uint32_t layer,
-                         uint32_t *x_offset_sa, uint32_t *y_offset_sa);
-
 #ifdef __cplusplus
 }
 #endif
-- 
2.9.3



More information about the mesa-dev mailing list