[Mesa-dev] [PATCH 12/27] i965/gen6: Calculate stencil offset on demand

Topi Pohjolainen topi.pohjolainen at gmail.com
Mon Jan 16 09:13:47 UTC 2017


This is kept on purpose in i965. It can be moved to ISL if it
is needed in vulkan.

Pointers to miptrees are given solely for verification purposes.
These will be dropped in following patches.

Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
---
 src/mesa/drivers/dri/i965/brw_tex_layout.c    | 65 +++++++++++++++++++++++++++
 src/mesa/drivers/dri/i965/gen6_depth_state.c  | 14 +++---
 src/mesa/drivers/dri/i965/intel_mipmap_tree.h |  5 +++
 3 files changed, 78 insertions(+), 6 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c
index 768f8a8..80b341a 100644
--- a/src/mesa/drivers/dri/i965/brw_tex_layout.c
+++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c
@@ -288,6 +288,71 @@ gen9_miptree_layout_1d(struct intel_mipmap_tree *mt)
    }
 }
 
+static unsigned
+all_slices_at_each_lod_x_offset(unsigned w0, unsigned align, unsigned level)
+{
+   const unsigned w = level >= 2 ? minify(w0, 1) : 0;
+   return ALIGN(w, align);
+}
+
+static unsigned
+all_slices_at_each_lod_y_offset(const struct isl_extent4d *phys_level0_sa,
+                                enum isl_surf_dim dim, unsigned align,
+                                unsigned level)
+{
+   unsigned y = 0;
+
+   /* Add vertical space taken by lower levels one by one. Levels one and two
+    * are side-by-side just below level zero. Levels three and greater are
+    * stacked one after another below level two.
+    */
+   for (unsigned i = 1; i <= level; ++i) {
+      const unsigned d = dim == ISL_SURF_DIM_3D ?
+                         minify(phys_level0_sa->depth, i - 1) :
+                         phys_level0_sa->array_len;
+
+      /* Levels two and greater are stacked just below level zero. */
+      if (i != 2) {
+         const unsigned h = minify(phys_level0_sa->height, i - 1);
+         y += d * ALIGN(h, align);
+      }
+   }
+
+   return y;
+}
+
+uint32_t
+brw_stencil_all_slices_at_each_lod_offset(const struct isl_surf *surf,
+                                          const struct intel_mipmap_tree *mt,
+                                          unsigned level)
+{
+   assert(mt->array_layout == ALL_SLICES_AT_EACH_LOD);
+
+   const unsigned halign = 64;
+   const unsigned valign = 64;
+   const unsigned level_x = all_slices_at_each_lod_x_offset(
+      surf->phys_level0_sa.width, halign, level);
+   const unsigned level_y = all_slices_at_each_lod_y_offset(
+      &surf->phys_level0_sa, surf->dim, valign, level);
+
+   assert(level_x == mt->level[level].level_x);
+   assert(level_y == mt->level[level].level_y);
+
+   /* From Vol 2a, 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface Pitch":
+    *    The pitch must be set to 2x the value computed based on width, as
+    *    the stencil buffer is stored with two rows interleaved.
+    *
+    * While ISL surface stores the pitch expected by hardware, the offset
+    * into individual slices needs to be calculated as if rows are
+    * interleaved.
+    */
+   const unsigned two_rows_interleaved_pitch = surf->row_pitch / 2;
+
+   assert(two_rows_interleaved_pitch == mt->pitch);
+
+   return level_y * two_rows_interleaved_pitch + level_x * 64;
+}
+
 static void
 brw_miptree_layout_2d(struct intel_mipmap_tree *mt)
 {
diff --git a/src/mesa/drivers/dri/i965/gen6_depth_state.c b/src/mesa/drivers/dri/i965/gen6_depth_state.c
index cda66e8..80cb890 100644
--- a/src/mesa/drivers/dri/i965/gen6_depth_state.c
+++ b/src/mesa/drivers/dri/i965/gen6_depth_state.c
@@ -189,15 +189,17 @@ gen6_emit_depth_stencil_hiz(struct brw_context *brw,
       if (separate_stencil) {
          uint32_t offset = 0;
 
+         struct isl_surf temp_surf;
+         intel_miptree_get_isl_surf(brw, stencil_mt, &temp_surf);
+
          if (stencil_mt->array_layout == ALL_SLICES_AT_EACH_LOD) {
             assert(stencil_mt->format == MESA_FORMAT_S_UINT8);
+            offset = brw_stencil_all_slices_at_each_lod_offset(
+                        &temp_surf, stencil_mt, lod);
 
-            /* Note: we can't compute the stencil offset using
-             * intel_region_get_aligned_offset(), because stencil_region
-             * claims that the region is untiled even though it's W tiled.
-             */
-            offset = stencil_mt->level[lod].level_y * stencil_mt->pitch +
-                     stencil_mt->level[lod].level_x * 64;
+            assert(offset ==
+                   stencil_mt->level[lod].level_y * stencil_mt->pitch +
+                   stencil_mt->level[lod].level_x * 64);
          }
 
 	 BEGIN_BATCH(3);
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
index 476c46b..e51872f 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
@@ -983,6 +983,11 @@ brw_miptree_get_vertical_slice_pitch(const struct brw_context *brw,
                                      const struct intel_mipmap_tree *mt,
                                      unsigned level);
 
+uint32_t
+brw_stencil_all_slices_at_each_lod_offset(const struct isl_surf *surf,
+                                          const struct intel_mipmap_tree *mt,
+                                          uint32_t level);
+
 void
 brw_miptree_layout(struct brw_context *brw,
                    struct intel_mipmap_tree *mt,
-- 
2.5.5



More information about the mesa-dev mailing list