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

Jason Ekstrand jason at jlekstrand.net
Sat Jan 21 00:35:23 UTC 2017


On Mon, Jan 16, 2017 at 1:13 AM, Topi Pohjolainen <
topi.pohjolainen at gmail.com> wrote:

> 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;
> +}
>

There's really no good place in this series to make this comment but I
think this is as good as I'm going to get...

I can't quite tell what your long-term plan is for gen6 stencil and HiZ.
Eventually, I'd like to kill the ALL_SLICES_AT_EACH_LOD stuff.  The only
reason why Jordan and the Igalia people did that in the first place was so
that they could re-use existing surface calculation code.  Really, the
requirement is that gen6 doesn't support multiple miplevels with HiZ and
Stencil even though it does support arrays.  The point of the
ALL_SLICES_AT_EACH_LOD layout is to, instead of making it an array of
miptrees, it lays it out into a bunch of single-LOD arrays.  The fact that
they happen to be layed out like a miptree is immaterial.

When Nanley and I were talking about this in the office, he had a very good
suggestion.  What he suggested was to just have an array of isl_surf's, one
for each miplevel and lay the single-LOD arrays out linearly in memory.  To
compute the size of the gen6 stencil or HiZ buffer you would do something
like this;

uint32_t size = 0;
for (level = 0; level < num_levels; level++) {
   isl_surf_init(&mt->gen6_per_level[level].surf,
              .width = minify(width, level),
              .height = minify(height, level),
              .depth = 1,
              .levels = 1,
              .array_len = array_len,
              .format = ISL_FORMAT_HIZ,
              ...);
   mt->gen6_per_level[level].offset = size;
   size += mt->gen6_per_level[level].surf.size;
}

Then in the gen6 hiz and stencil setup code, you would just offset it by
mt->gen6_per_level[level].offset and be done with it.  There's no real
reason why we need to keep all this ALL_SLICES_AT_EACH_LOD calculation
stuff indefinitely.  We just need some way of putting all of the per-LOD
images in the same BO.  (Technically, they don't even need to go in the
same BO but it's kind of nice to do it that way.)

Thoughts?

--Jason


> +
>  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
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20170120/4747ea5b/attachment.html>


More information about the mesa-dev mailing list