[Mesa-dev] [PATCH 08/11] intel/isl: Add a new layout for HiZ and stencil on Sandy Bridge
Jason Ekstrand
jason at jlekstrand.net
Thu Jun 1 15:30:16 UTC 2017
On Thu, Jun 1, 2017 at 2:40 AM, Pohjolainen, Topi <
topi.pohjolainen at gmail.com> wrote:
> On Tue, May 30, 2017 at 05:55:17PM -0700, Jason Ekstrand wrote:
> > ---
> > src/intel/isl/isl.c | 162 ++++++++++++++++++++++++++++++
> ++++++++++++++++++++--
> > src/intel/isl/isl.h | 40 +++++++++++++
> > 2 files changed, 197 insertions(+), 5 deletions(-)
> >
> > diff --git a/src/intel/isl/isl.c b/src/intel/isl/isl.c
> > index 77b8a40..e4d7901 100644
> > --- a/src/intel/isl/isl.c
> > +++ b/src/intel/isl/isl.c
> > @@ -479,6 +479,12 @@ isl_choose_array_pitch_span(const struct
> isl_device *dev,
> > * compact QPitch possible in order to conserve memory.
> > */
> > return ISL_ARRAY_PITCH_SPAN_COMPACT;
> > +
> > + case ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ:
> > + /* Each array image in the gen6 stencil of HiZ surface is compact
> in the
> > + * sense that every LOD is a compact array of the same size as
> LOD0.
> > + */
> > + return ISL_ARRAY_PITCH_SPAN_COMPACT;
> > }
> >
> > unreachable("bad isl_dim_layout");
> > @@ -510,10 +516,15 @@ isl_choose_image_alignment_el(const struct
> isl_device *dev,
> > return;
> > } else if (info->format == ISL_FORMAT_HIZ) {
> > assert(ISL_DEV_GEN(dev) >= 6);
> > - /* HiZ surfaces are always aligned to 16x8 pixels in the primary
> surface
> > - * which works out to 2x2 HiZ elments.
> > - */
> > - *image_align_el = isl_extent3d(2, 2, 1);
> > + if (ISL_DEV_GEN(dev) == 6) {
> > + /* HiZ surfaces on Sandy Bridge are packed tightly. */
> > + *image_align_el = isl_extent3d(1, 1, 1);
> > + } else {
> > + /* On gen7+, HiZ surfaces are always aligned to 16x8 pixels in
> the
> > + * primary surface which works out to 2x2 HiZ elments.
> > + */
> > + *image_align_el = isl_extent3d(2, 2, 1);
> > + }
> > return;
> > }
> >
> > @@ -540,6 +551,11 @@ isl_surf_choose_dim_layout(const struct isl_device
> *dev,
> > enum isl_surf_dim logical_dim,
> > enum isl_tiling tiling)
> > {
> > + /* Sandy bridge needs a special layout for HiZ and stencil. */
> > + if (ISL_DEV_GEN(dev) == 6 &&
> > + (tiling == ISL_TILING_W || tiling == ISL_TILING_HIZ))
> > + return ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ;
> > +
> > if (ISL_DEV_GEN(dev) >= 9) {
> > switch (logical_dim) {
> > case ISL_SURF_DIM_1D:
> > @@ -608,6 +624,7 @@ isl_calc_phys_level0_extent_sa(const struct
> isl_device *dev,
> >
> > case ISL_DIM_LAYOUT_GEN9_1D:
> > case ISL_DIM_LAYOUT_GEN4_2D:
> > + case ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ:
> > *phys_level0_sa = (struct isl_extent4d) {
> > .w = isl_align_npot(info->width, fmtl->bw),
> > .h = fmtl->bh,
> > @@ -619,7 +636,8 @@ isl_calc_phys_level0_extent_sa(const struct
> isl_device *dev,
> > break;
> >
> > case ISL_SURF_DIM_2D:
> > - assert(dim_layout == ISL_DIM_LAYOUT_GEN4_2D);
> > + assert(dim_layout == ISL_DIM_LAYOUT_GEN4_2D ||
> > + dim_layout == ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ);
> >
> > if (tiling == ISL_TILING_Ys && info->samples > 1)
> > isl_finishme("%s:%s: multisample TileYs layout", __FILE__,
> __func__);
> > @@ -684,6 +702,7 @@ isl_calc_phys_level0_extent_sa(const struct
> isl_device *dev,
> >
> > switch (dim_layout) {
> > case ISL_DIM_LAYOUT_GEN9_1D:
> > + case ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ:
> > unreachable("bad isl_dim_layout");
> >
> > case ISL_DIM_LAYOUT_GEN4_2D:
> > @@ -969,6 +988,67 @@ isl_calc_phys_total_extent_el_gen4_3d(
> >
> > /**
> > * A variant of isl_calc_phys_slice0_extent_sa() specific to
> > + * ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ.
> > + */
> > +static void
> > +isl_calc_phys_total_extent_el_gen6_stencil_hiz(
> > + const struct isl_device *dev,
> > + const struct isl_surf_init_info *restrict info,
> > + const struct isl_tile_info *tile_info,
> > + const struct isl_extent3d *image_align_sa,
> > + const struct isl_extent4d *phys_level0_sa,
> > + uint32_t *array_pitch_el_rows,
> > + struct isl_extent2d *phys_total_el)
> > +{
> > + const struct isl_format_layout *fmtl = isl_format_get_layout(info->
> format);
> > +
> > + const struct isl_extent2d tile_extent_sa = {
> > + .w = tile_info->logical_extent_el.w * fmtl->bw,
> > + .h = tile_info->logical_extent_el.h * fmtl->bh,
> > + };
> > + /* Tile size is a multiple of image alignment */
> > + assert(tile_extent_sa.w % image_align_sa->w == 0);
> > + assert(tile_extent_sa.h % image_align_sa->h == 0);
> > +
> > + const uint32_t W0 = phys_level0_sa->w;
> > + const uint32_t H0 = phys_level0_sa->h;
> > +
> > + /* Each image has the same height as LOD0 because the hardware thinks
> > + * everything is LOD0
> > + */
> > + const uint32_t H = isl_align(H0, image_align_sa->h) *
> phys_level0_sa->a;
> > +
> > + uint32_t slice_top_w = 0;
> > + uint32_t slice_bottom_w = 0;
> > + uint32_t slice_h = 0;
>
> I don't really understand why slice_bottom_w and slice_h are prefixed with
> slice, I would rather call them total_bottom_w and total_h.
>
Yeah, "total" is better. "slice" was just a carry-over from my initial
copy+paste of the gen4_2d code. I'll fix it.
> > +
> > + for (uint32_t l = 0; l < info->levels; ++l) {
> > + const uint32_t W = isl_minify(W0, l);
> > +
> > + const uint32_t w = isl_align(W, tile_extent_sa.w);
> > + const uint32_t h = isl_align(H, tile_extent_sa.h);
> > +
> > + if (l == 0) {
> > + slice_top_w = w;
> > + slice_h = h;
> > + } else if (l == 1) {
> > + slice_bottom_w = w;
> > + slice_h += h;
> > + } else {
> > + slice_bottom_w += w;
> > + }
> > + }
> > +
> > + *array_pitch_el_rows =
> > + isl_assert_div(isl_align(H0, image_align_sa->h), fmtl->bh);
> > + *phys_total_el = (struct isl_extent2d) {
> > + .w = isl_assert_div(MAX(slice_top_w, slice_bottom_w), fmtl->bw),
> > + .h = isl_assert_div(slice_h, fmtl->bh),
> > + };
> > +}
> > +
> > +/**
> > + * A variant of isl_calc_phys_slice0_extent_sa() specific to
> > * ISL_DIM_LAYOUT_GEN9_1D.
> > */
> > static void
> > @@ -1035,6 +1115,14 @@ isl_calc_phys_total_extent_el(const struct
> isl_device *dev,
> > array_pitch_el_rows,
> > total_extent_el);
> > return;
> > + case ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ:
> > + assert(array_pitch_span == ISL_ARRAY_PITCH_SPAN_COMPACT);
> > + isl_calc_phys_total_extent_el_gen6_stencil_hiz(dev, info,
> tile_info,
> > + image_align_sa,
> > + phys_level0_sa,
> > +
> array_pitch_el_rows,
> > + total_extent_el);
> > + return;
> > case ISL_DIM_LAYOUT_GEN4_3D:
> > assert(array_pitch_span == ISL_ARRAY_PITCH_SPAN_COMPACT);
> > isl_calc_phys_total_extent_el_gen4_3d(dev, info,
> > @@ -1892,6 +1980,65 @@ get_image_offset_sa_gen4_3d(const struct
> isl_surf *surf,
> > *y_offset_sa = y;
> > }
> >
> > +static void
> > +get_image_offset_sa_gen6_stencil_hiz(const struct isl_surf *surf,
> > + uint32_t level,
> > + uint32_t logical_array_layer,
> > + uint32_t *x_offset_sa,
> > + uint32_t *y_offset_sa)
> > +{
> > + assert(level < surf->levels);
> > + assert(surf->logical_level0_px.depth == 1);
> > + assert(logical_array_layer < surf->logical_level0_px.array_len);
> > +
> > + const struct isl_format_layout *fmtl = isl_format_get_layout(surf->
> format);
> > +
> > + const struct isl_extent3d image_align_sa =
> > + isl_surf_get_image_alignment_sa(surf);
> > +
> > + struct isl_tile_info tile_info;
> > + isl_tiling_get_info(surf->tiling, fmtl->bpb, &tile_info);
> > + const struct isl_extent2d tile_extent_sa = {
> > + .w = tile_info.logical_extent_el.w * fmtl->bw,
> > + .h = tile_info.logical_extent_el.h * fmtl->bh,
> > + };
> > + /* Tile size is a multiple of image alignment */
> > + assert(tile_extent_sa.w % image_align_sa.w == 0);
> > + assert(tile_extent_sa.h % image_align_sa.h == 0);
> > +
> > + const uint32_t W0 = surf->phys_level0_sa.w;
> > + const uint32_t H0 = surf->phys_level0_sa.h;
> > +
> > + /* Each image has the same height as LOD0 because the hardware thinks
> > + * everything is LOD0
> > + */
> > + const uint32_t H = isl_align(H0, image_align_sa.h);
> > +
> > + /* Quick sanity check for consistency */
> > + if (surf->phys_level0_sa.array_len > 1)
> > + assert(surf->array_pitch_el_rows == isl_assert_div(H, fmtl->bh));
> > +
> > + uint32_t x = 0, y = 0;
> > + for (uint32_t l = 0; l < level; ++l) {
> > + const uint32_t W = isl_minify(W0, l);
> > +
> > + const uint32_t w = isl_align(W, tile_extent_sa.w);
> > + const uint32_t h = isl_align(H * surf->phys_level0_sa.a,
> > + tile_extent_sa.h);
> > +
> > + if (l == 0) {
> > + y += h;
> > + } else {
> > + x += w;
>
> For "l == 1", "x" should still be zero?
>
Yes, that's correct.
> > + }
> > + }
> > +
> > + y += H * logical_array_layer;
> > +
> > + *x_offset_sa = x;
> > + *y_offset_sa = y;
> > +}
> > +
> > /**
> > * A variant of isl_surf_get_image_offset_sa() specific to
> > * ISL_DIM_LAYOUT_GEN9_1D.
> > @@ -1961,6 +2108,11 @@ isl_surf_get_image_offset_sa(const struct
> isl_surf *surf,
> > logical_z_offset_px,
> > x_offset_sa, y_offset_sa);
> > break;
> > + case ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ:
> > + get_image_offset_sa_gen6_stencil_hiz(surf, level,
> logical_array_layer +
> > + logical_z_offset_px,
> > + x_offset_sa, y_offset_sa);
> > + break;
> >
> > default:
> > unreachable("not reached");
> > diff --git a/src/intel/isl/isl.h b/src/intel/isl/isl.h
> > index 008ab5e..4bb3de7 100644
> > --- a/src/intel/isl/isl.h
> > +++ b/src/intel/isl/isl.h
> > @@ -528,6 +528,46 @@ enum isl_dim_layout {
> > ISL_DIM_LAYOUT_GEN4_3D,
> >
> > /**
> > + * Special layout used for HiZ and stencil on Sandy Bridge to work
> around
> > + * the hardware's lack of mipmap support. On gen6, HiZ and stencil
> buffers
> > + * work the same as on gen7+ except that they don't technically
> support
> > + * mipmapping. That does not, however, stop us from doing it. As
> far as
> > + * Sandy Bridge hardware is concerned, HiZ and stencil always
> operates on a
> > + * single miplevel 2D (possibly array) image. The dimensions of
> that image
> > + * are NOT minified.
> > + *
> > + * In order to implement HiZ and stencil on Sandy Bridge, we create
> one
> > + * full-sized 2D (possibly array) image for every LOD with every
> image
> > + * aligned to a page boundary. When the surface is used with the
> stencil
> > + * or HiZ hardware, we manually offset to the image for the given
> LOD.
> > + *
> > + * As a memory saving measure, we pretend that the width of each
> miplevel
> > + * is minified and we place LOD1 and above below LOD0 but
> horizontally
> > + * adjacent to each other. When considered as full-sized images,
> LOD1 and
> > + * above technically overlap. However, since we only write to part
> of that
> > + * image, the hardware will never notice the overlap.
> > + *
> > + * This layout looks something like this:
> > + *
> > + * +---------+
> > + * | |
> > + * | |
> > + * +---------+
> > + * | |
> > + * | |
> > + * +---------+
> > + *
> > + * +----+ +-+ .
> > + * | | +-+
> > + * +----+
> > + *
> > + * +----+ +-+ .
> > + * | | +-+
> > + * +----+
> > + */
> > + ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ,
> > +
> > + /**
> > * For details, see the Skylake BSpec >> Memory Views >> Common
> Surface
> > * Formats >> Surface Layout and Tiling >> ยป 1D Surfaces.
> > */
> > --
> > 2.5.0.400.gff86faf
> >
> > _______________________________________________
> > 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/20170601/f0f52284/attachment-0001.html>
More information about the mesa-dev
mailing list