<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sat, Jan 21, 2017 at 1:19 AM, Pohjolainen, Topi <span dir="ltr"><<a href="mailto:topi.pohjolainen@gmail.com" target="_blank">topi.pohjolainen@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Fri, Jan 20, 2017 at 04:35:23PM -0800, Jason Ekstrand wrote:<br>
>    On Mon, Jan 16, 2017 at 1:13 AM, Topi Pohjolainen<br>
</span><span class="">>    <[1]<a href="mailto:topi.pohjolainen@gmail.com">topi.pohjolainen@gmail.com</a><wbr>> wrote:<br>
><br>
>      This is kept on purpose in i965. It can be moved to ISL if it<br>
>      is needed in vulkan.<br>
>      Pointers to miptrees are given solely for verification purposes.<br>
>      These will be dropped in following patches.<br>
</span>>      Signed-off-by: Topi Pohjolainen <[2]<a href="mailto:topi.pohjolainen@intel.com">topi.pohjolainen@intel.com</a><wbr>><br>
<div><div class="h5">>      ---<br>
>       src/mesa/drivers/dri/i965/brw_<wbr>tex_layout.c    | 65<br>
>      +++++++++++++++++++++++++++<br>
>       src/mesa/drivers/dri/i965/<wbr>gen6_depth_state.c  | 14 +++---<br>
>       src/mesa/drivers/dri/i965/<wbr>intel_mipmap_tree.h |  5 +++<br>
>       3 files changed, 78 insertions(+), 6 deletions(-)<br>
>      diff --git a/src/mesa/drivers/dri/i965/<wbr>brw_tex_layout.c<br>
>      b/src/mesa/drivers/dri/i965/<wbr>brw_tex_layout.c<br>
>      index 768f8a8..80b341a 100644<br>
>      --- a/src/mesa/drivers/dri/i965/<wbr>brw_tex_layout.c<br>
>      +++ b/src/mesa/drivers/dri/i965/<wbr>brw_tex_layout.c<br>
>      @@ -288,6 +288,71 @@ gen9_miptree_layout_1d(struct intel_mipmap_tree<br>
>      *mt)<br>
>          }<br>
>       }<br>
>      +static unsigned<br>
>      +all_slices_at_each_lod_x_<wbr>offset(unsigned w0, unsigned align,<br>
>      unsigned level)<br>
>      +{<br>
>      +   const unsigned w = level >= 2 ? minify(w0, 1) : 0;<br>
>      +   return ALIGN(w, align);<br>
>      +}<br>
>      +<br>
>      +static unsigned<br>
>      +all_slices_at_each_lod_y_<wbr>offset(const struct isl_extent4d<br>
>      *phys_level0_sa,<br>
>      +                                enum isl_surf_dim dim, unsigned<br>
>      align,<br>
>      +                                unsigned level)<br>
>      +{<br>
>      +   unsigned y = 0;<br>
>      +<br>
>      +   /* Add vertical space taken by lower levels one by one. Levels<br>
>      one and two<br>
>      +    * are side-by-side just below level zero. Levels three and<br>
>      greater are<br>
>      +    * stacked one after another below level two.<br>
>      +    */<br>
>      +   for (unsigned i = 1; i <= level; ++i) {<br>
>      +      const unsigned d = dim == ISL_SURF_DIM_3D ?<br>
>      +                         minify(phys_level0_sa->depth, i - 1) :<br>
>      +                         phys_level0_sa->array_len;<br>
>      +<br>
>      +      /* Levels two and greater are stacked just below level zero.<br>
>      */<br>
>      +      if (i != 2) {<br>
>      +         const unsigned h = minify(phys_level0_sa->height, i - 1);<br>
>      +         y += d * ALIGN(h, align);<br>
>      +      }<br>
>      +   }<br>
>      +<br>
>      +   return y;<br>
>      +}<br>
>      +<br>
>      +uint32_t<br>
>      +brw_stencil_all_slices_at_<wbr>each_lod_offset(const struct isl_surf<br>
>      *surf,<br>
>      +                                          const struct<br>
>      intel_mipmap_tree *mt,<br>
>      +                                          unsigned level)<br>
>      +{<br>
>      +   assert(mt->array_layout == ALL_SLICES_AT_EACH_LOD);<br>
>      +<br>
>      +   const unsigned halign = 64;<br>
>      +   const unsigned valign = 64;<br>
>      +   const unsigned level_x = all_slices_at_each_lod_x_<wbr>offset(<br>
>      +      surf->phys_level0_sa.width, halign, level);<br>
>      +   const unsigned level_y = all_slices_at_each_lod_y_<wbr>offset(<br>
>      +      &surf->phys_level0_sa, surf->dim, valign, level);<br>
>      +<br>
>      +   assert(level_x == mt->level[level].level_x);<br>
>      +   assert(level_y == mt->level[level].level_y);<br>
>      +<br>
>      +   /* From Vol 2a, 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field<br>
>      "Surface Pitch":<br>
>      +    *    The pitch must be set to 2x the value computed based on<br>
>      width, as<br>
>      +    *    the stencil buffer is stored with two rows interleaved.<br>
>      +    *<br>
>      +    * While ISL surface stores the pitch expected by hardware, the<br>
>      offset<br>
>      +    * into individual slices needs to be calculated as if rows are<br>
>      +    * interleaved.<br>
>      +    */<br>
>      +   const unsigned two_rows_interleaved_pitch = surf->row_pitch / 2;<br>
>      +<br>
>      +   assert(two_rows_interleaved_<wbr>pitch == mt->pitch);<br>
>      +<br>
>      +   return level_y * two_rows_interleaved_pitch + level_x * 64;<br>
>      +}<br>
><br>
>    There's really no good place in this series to make this comment but I<br>
>    think this is as good as I'm going to get...<br>
>    I can't quite tell what your long-term plan is for gen6 stencil and<br>
>    HiZ.  Eventually, I'd like to kill the ALL_SLICES_AT_EACH_LOD stuff.<br>
>    The only reason why Jordan and the Igalia people did that in the first<br>
>    place was so that they could re-use existing surface calculation code.<br>
>    Really, the requirement is that gen6 doesn't support multiple miplevels<br>
>    with HiZ and Stencil even though it does support arrays.  The point of<br>
>    the ALL_SLICES_AT_EACH_LOD layout is to, instead of making it an array<br>
>    of miptrees, it lays it out into a bunch of single-LOD arrays.  The<br>
>    fact that they happen to be layed out like a miptree is immaterial.<br>
>    When Nanley and I were talking about this in the office, he had a very<br>
>    good suggestion.  What he suggested was to just have an array of<br>
>    isl_surf's, one for each miplevel and lay the single-LOD arrays out<br>
>    linearly in memory.  To compute the size of the gen6 stencil or HiZ<br>
>    buffer you would do something like this;<br>
>    uint32_t size = 0;<br>
>    for (level = 0; level < num_levels; level++) {<br>
>       isl_surf_init(&mt->gen6_per_<wbr>level[level].surf,<br>
>                  .width = minify(width, level),<br>
>                  .height = minify(height, level),<br>
>                  .depth = 1,<br>
>                  .levels = 1,<br>
>                  .array_len = array_len,<br>
>                  .format = ISL_FORMAT_HIZ,<br>
>                  ...);<br>
>       mt->gen6_per_level[level].<wbr>offset = size;<br>
>       size += mt->gen6_per_level[level].<wbr>surf.size;<br>
>    }<br>
>    Then in the gen6 hiz and stencil setup code, you would just offset it<br>
>    by mt->gen6_per_level[level].<wbr>offset and be done with it.  There's no<br>
>    real reason why we need to keep all this ALL_SLICES_AT_EACH_LOD<br>
>    calculation stuff indefinitely.  We just need some way of putting all<br>
>    of the per-LOD images in the same BO.  (Technically, they don't even<br>
>    need to go in the same BO but it's kind of nice to do it that way.)<br>
>    Thoughts?<br>
<br>
</div></div>This might be becoming a matter of taste debate. I'm probably thinking too<br>
much from "what does the hw setup need"-point of view. I'm thinking that<br>
as the hw really only wants offset and row pitch why do we need to maintain<br>
all the extra information. This is afterall something that can be calculated<br>
relatively straight forward if needs be. And the need is not clear - as hw<br>
setup don't need it, what is it for? Accessing individual slices using cpu<br>
is also just about the offset and shifting the base level dimensions.<br>
<br>
Also continuing with matter of taste. I'm not a big fan of storing information<br>
in tables if it is used infrequently and rather cheap to produce on-demand.<br>
(I'm seeing the array of isl_surf instances as a pre-computed lookup table).<br></blockquote><div><br></div><div>Honestly, I'm not married to the idea of storing all of the isl_surf's for each slice.  We can store them or not.  It was mostly about laying things out sequentially in memory rather than trying to place all of these single-LOD arrays in some sort of 2-D mipmap layout.  Among other things, doing so wastes space compared to just storing the different LODs sequentially.  Also, it makes for a bunch of painful calculations that we're doing for really no good reason.  The calculation for the offset could be just a sum of the sizes of the previous miplevels.<br></div></div></div></div>