<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Fri, Jun 2, 2017 at 4:30 PM, Nanley Chery <span dir="ltr"><<a href="mailto:nanleychery@gmail.com" target="_blank">nanleychery@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, May 26, 2017 at 04:30:19PM -0700, Jason Ekstrand wrote:<br>
</span><div><div class="h5">> This commit adds a new unified interface for doing resolves.  The basic<br>
> format is that, prior to any surface access such as texturing or<br>
> rendering, you call intel_miptree_prepare_access.  If the surface was<br>
> written, you call intel_miptree_finish_write.  These two functions take<br>
> parameters which tell them whether or not auxiliary compression and fast<br>
> clears are supported on the surface.  Later commits will add wrappers<br>
> around these two functions for texturing, rendering, etc.<br>
> ---<br>
>  src/mesa/drivers/dri/i965/<wbr>intel_mipmap_tree.c | 156 +++++++++++++++++++++++++-<br>
>  src/mesa/drivers/dri/i965/<wbr>intel_mipmap_tree.h |  80 +++++++++++++<br>
>  2 files changed, 232 insertions(+), 4 deletions(-)<br>
><br>
> diff --git a/src/mesa/drivers/dri/i965/<wbr>intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/<wbr>intel_mipmap_tree.c<br>
> index 6cd32ce..0659e75 100644<br>
> --- a/src/mesa/drivers/dri/i965/<wbr>intel_mipmap_tree.c<br>
> +++ b/src/mesa/drivers/dri/i965/<wbr>intel_mipmap_tree.c<br>
> @@ -2028,8 +2028,7 @@ bool<br>
>  intel_miptree_all_slices_<wbr>resolve_hiz(struct brw_context *brw,<br>
>                                    struct intel_mipmap_tree *mt)<br>
>  {<br>
> -   return intel_miptree_depth_hiz_<wbr>resolve(brw, mt,<br>
> -                                          0, UINT32_MAX, 0, UINT32_MAX,<br>
> +   return intel_miptree_depth_hiz_<wbr>resolve(brw, mt, 0, UINT32_MAX, 0, UINT32_MAX,<br>
>                                            BLORP_HIZ_OP_HIZ_RESOLVE);<br>
>  }<br>
><br>
> @@ -2037,8 +2036,7 @@ bool<br>
>  intel_miptree_all_slices_<wbr>resolve_depth(struct brw_context *brw,<br>
>                                      struct intel_mipmap_tree *mt)<br>
>  {<br>
> -   return intel_miptree_depth_hiz_<wbr>resolve(brw, mt,<br>
> -                                          0, UINT32_MAX, 0, UINT32_MAX,<br>
> +   return intel_miptree_depth_hiz_<wbr>resolve(brw, mt, 0, UINT32_MAX, 0, UINT32_MAX,<br>
>                                            BLORP_HIZ_OP_DEPTH_RESOLVE);<br>
>  }<br>
><br>
> @@ -2221,6 +2219,156 @@ intel_miptree_all_slices_<wbr>resolve_color(struct brw_context *brw,<br>
>     intel_miptree_resolve_color(<wbr>brw, mt, 0, UINT32_MAX, 0, UINT32_MAX, flags);<br>
>  }<br>
><br>
> +void<br>
> +intel_miptree_prepare_access(<wbr>struct brw_context *brw,<br>
> +                             struct intel_mipmap_tree *mt,<br>
> +                             uint32_t start_level, uint32_t num_levels,<br>
> +                             uint32_t start_layer, uint32_t num_layers,<br>
> +                             bool aux_supported, bool fast_clear_supported)<br>
> +{<br>
> +   if (_mesa_is_format_color_format(<wbr>mt->format)) {<br>
> +      if (!mt->mcs_buf)<br>
> +         return;<br>
> +<br>
> +      if (mt->num_samples > 1) {<br>
> +         /* Nothing to do for MSAA */<br>
> +      } else {<br>
> +         /* TODO: This is fairly terrible.  We can do better. */<br>
> +         if (!aux_supported || !fast_clear_supported) {<br>
> +            intel_miptree_resolve_color(<wbr>brw, mt, start_level, num_levels,<br>
> +                                        start_layer, num_layers, 0);<br>
> +         }<br>
> +      }<br>
> +   } else if (mt->format == MESA_FORMAT_S_UINT8) {<br>
> +      /* Nothing to do for stencil */<br>
> +   } else {<br>
> +      if (!mt->hiz_buf)<br>
> +         return;<br>
> +<br>
> +      if (aux_supported) {<br>
> +         assert(fast_clear_supported);<br>
> +         intel_miptree_depth_hiz_<wbr>resolve(brw, mt, start_level, num_levels,<br>
> +                                         start_layer, num_layers,<br>
> +                                         BLORP_HIZ_OP_HIZ_RESOLVE);<br>
> +      } else {<br>
> +         assert(!fast_clear_supported);<br>
> +         intel_miptree_depth_hiz_<wbr>resolve(brw, mt, start_level, num_levels,<br>
> +                                         start_layer, num_layers,<br>
> +                                         BLORP_HIZ_OP_DEPTH_RESOLVE);<br>
> +      }<br>
> +   }<br>
> +}<br>
> +<br>
> +void<br>
> +intel_miptree_finish_write(<wbr>struct brw_context *brw,<br>
> +                           struct intel_mipmap_tree *mt, uint32_t level,<br>
> +                           uint32_t start_layer, uint32_t num_layers,<br>
> +                           bool written_with_aux)<br>
> +{<br>
> +   assert(start_layer < mt->level[level].depth);<br>
> +   if (num_layers == INTEL_REMAINING_LAYERS)<br>
> +      num_layers = mt->level[level].depth - start_layer;<br>
> +   assert(num_layers <= mt->level[level].depth - start_layer);<br>
> +<br>
> +   if (_mesa_is_format_color_format(<wbr>mt->format)) {<br>
> +      if (mt->num_samples > 1) {<br>
> +         /* Nothing to do for MSAA */<br>
> +      } else {<br>
> +         if (written_with_aux) {<br>
> +            intel_miptree_used_for_<wbr>rendering(brw, mt, level,<br>
> +                                             start_layer, num_layers);<br>
> +         }<br>
> +      }<br>
> +   } else if (mt->format == MESA_FORMAT_S_UINT8) {<br>
> +      /* Nothing to do for stencil */<br>
> +   } else {<br>
> +      if (written_with_aux) {<br>
> +         for (unsigned a = 0; a < num_layers; a++) {<br>
> +            intel_miptree_check_level_<wbr>layer(mt, level, start_layer);<br>
> +            intel_miptree_slice_set_needs_<wbr>depth_resolve(mt, level,<br>
> +                                                        start_layer + a);<br>
> +         }<br>
> +      } else {<br>
> +         for (unsigned a = 0; a < num_layers; a++) {<br>
> +            intel_miptree_check_level_<wbr>layer(mt, level, start_layer);<br>
> +            intel_miptree_slice_set_needs_<wbr>hiz_resolve(mt, level,<br>
> +                                                      start_layer + a);<br>
> +         }<br>
> +      }<br>
> +   }<br>
> +}<br>
> +<br>
> +enum isl_aux_state<br>
> +intel_miptree_get_aux_state(<wbr>const struct intel_mipmap_tree *mt,<br>
> +                            uint32_t level, uint32_t layer)<br>
> +{<br>
> +   if (_mesa_is_format_color_format(<wbr>mt->format)) {<br>
> +      assert(mt->mcs_buf != NULL);<br>
> +      if (mt->num_samples > 1) {<br>
> +         return ISL_AUX_STATE_COMPRESSED_<wbr>CLEAR;<br>
> +      } else {<br>
> +         switch (intel_miptree_get_fast_clear_<wbr>state(mt, level, layer)) {<br>
> +         case INTEL_FAST_CLEAR_STATE_<wbr>RESOLVED:<br>
> +            return ISL_AUX_STATE_RESOLVED;<br>
> +         case INTEL_FAST_CLEAR_STATE_<wbr>UNRESOLVED:<br>
> +            return ISL_AUX_STATE_COMPRESSED_<wbr>CLEAR;<br>
> +         case INTEL_FAST_CLEAR_STATE_CLEAR:<br>
> +            return ISL_AUX_STATE_CLEAR;<br>
> +         default:<br>
> +            unreachable("Invalid fast clear state");<br>
> +         }<br>
> +      }<br>
> +   } else if (mt->format == MESA_FORMAT_S_UINT8) {<br>
> +      unreachable("Cannot get aux state for stencil");<br>
> +   } else {<br>
> +      assert(mt->hiz_buf != NULL);<br>
> +      const struct intel_resolve_map *map =<br>
> +         intel_resolve_map_const_get(&<wbr>mt->hiz_map, level, layer);<br>
> +      if (!map)<br>
> +         return ISL_AUX_STATE_RESOLVED;<br>
> +      switch (map->need) {<br>
> +      case BLORP_HIZ_OP_DEPTH_RESOLVE:<br>
> +         return ISL_AUX_STATE_COMPRESSED_<wbr>CLEAR;<br>
> +      case BLORP_HIZ_OP_HIZ_RESOLVE:<br>
> +         return ISL_AUX_STATE_AUX_INVALID;<br>
> +      default:<br>
> +         unreachable("Invalid hiz op");<br>
> +      }<br>
> +   }<br>
> +}<br>
> +<br>
> +void<br>
> +intel_miptree_set_aux_state(<wbr>struct brw_context *brw,<br>
> +                            struct intel_mipmap_tree *mt, uint32_t level,<br>
> +                            uint32_t start_layer, uint32_t num_layers,<br>
> +                            enum isl_aux_state aux_state)<br>
> +{<br>
> +   assert(start_layer < mt->level[level].depth);<br>
> +   if (num_layers == INTEL_REMAINING_LAYERS)<br>
> +      num_layers = mt->level[level].depth - start_layer;<br>
> +   assert(num_layers <= mt->level[level].depth - start_layer);<br>
> +<br>
> +   /* Right now, this only applies to clears. */<br>
> +   assert(aux_state == ISL_AUX_STATE_CLEAR);<br>
> +<br>
> +   if (_mesa_is_format_color_format(<wbr>mt->format)) {<br>
> +      if (mt->num_samples > 1)<br>
> +         assert(mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS);<br>
> +<br>
> +      assert(level == 0 && start_layer == 0 && num_layers == 1);<br>
> +      intel_miptree_set_fast_clear_<wbr>state(brw, mt, 0, 0, 1,<br>
> +                                         INTEL_FAST_CLEAR_STATE_CLEAR);<br>
> +   } else if (mt->format == MESA_FORMAT_S_UINT8) {<br>
> +      assert(!"Cannot set aux state for stencil");<br>
> +   } else {<br>
> +      for (unsigned a = 0; a < num_layers; a++) {<br>
> +         intel_miptree_check_level_<wbr>layer(mt, level, start_layer);<br>
> +         intel_miptree_slice_set_needs_<wbr>depth_resolve(mt, level,<br>
> +                                                     start_layer + a);<br>
> +      }<br>
> +   }<br>
> +}<br>
> +<br>
>  /**<br>
>   * Make it possible to share the BO backing the given miptree with another<br>
>   * process or another miptree.<br>
> diff --git a/src/mesa/drivers/dri/i965/<wbr>intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/<wbr>intel_mipmap_tree.h<br>
> index ffcedef..e74fca6 100644<br>
> --- a/src/mesa/drivers/dri/i965/<wbr>intel_mipmap_tree.h<br>
> +++ b/src/mesa/drivers/dri/i965/<wbr>intel_mipmap_tree.h<br>
> @@ -912,6 +912,86 @@ intel_miptree_all_slices_<wbr>resolve_color(struct brw_context *brw,<br>
>                                         struct intel_mipmap_tree *mt,<br>
>                                         int flags);<br>
><br>
> +#define INTEL_REMAINING_LAYERS UINT32_MAX<br>
> +#define INTEL_REMAINING_LEVELS UINT32_MAX<br>
> +<br>
> +/** Prepare a miptree for access<br>
> + *<br>
> + * This function should be called prior to any access to miptree in order to<br>
> + * perform any needed resolves.<br>
> + *<br>
> + * \param[in]  start_level    The first mip level to be accessed<br>
> + *<br>
> + * \param[in]  num_levels     The number of miplevels to be accessed or<br>
> + *                            INTEL_REMAINING_LEVELS to indicate every level<br>
> + *                            above start_level will be accessed<br>
> + *<br>
> + * \param[in]  start_layer    The first array slice or 3D layer to be accessed<br>
> + *<br>
> + * \param[in]  num_layers     The number of array slices or 3D layers be<br>
> + *                            accessed or INTEL_REMAINING_LAYERS to indicate<br>
> + *                            every layer above start_layer will be accessed<br>
> + *<br>
> + * \param[in]  aux_supported  Whether or not the access will support the<br>
> + *                            miptree's auxiliary compression format;  this<br>
> + *                            must be false for uncompressed miptrees<br>
> + *<br>
> + * \param[in]  fast_clear_supported Whether or not the access will support<br>
> + *                                  fast clears in the miptree's auxiliary<br>
> + *                                  compression format<br>
> + */<br>
> +void<br>
> +intel_miptree_prepare_access(<wbr>struct brw_context *brw,<br>
> +                             struct intel_mipmap_tree *mt,<br>
> +                             uint32_t start_level, uint32_t num_levels,<br>
> +                             uint32_t start_layer, uint32_t num_layers,<br>
> +                             bool aux_supported, bool fast_clear_supported);<br>
> +<br>
> +/** Complete a write operation<br>
> + *<br>
> + * This function should be called after any operation writes to a miptree.<br>
> + * This will update the miptree's compression state so that future resolves<br>
> + * happen correctly.  Technically, this function can be called before the<br>
> + * write occurs but the caller must ensure that they don't interlace<br>
> + * intel_miptree_prepare_access and intel_miptree_finish_write calls to<br>
> + * overlapping layer/level ranges.<br>
> + *<br>
> + * \param[in]  level             The mip level that was written<br>
> + *<br>
> + * \param[in]  start_layer       The first array slice or 3D layer written<br>
> + *<br>
> + * \param[in]  num_layers        The number of array slices or 3D layers<br>
> + *                               written or INTEL_REMAINING_LAYERS to indicate<br>
> + *                               every layer above start_layer was written<br>
> + *<br>
> + * \param[in]  written_with_aux  Whether or not the write was done with<br>
> + *                               auxiliary compression enabled<br>
> + */<br>
> +void<br>
> +intel_miptree_finish_write(<wbr>struct brw_context *brw,<br>
> +                           struct intel_mipmap_tree *mt, uint32_t level,<br>
> +                           uint32_t start_layer, uint32_t num_layers,<br>
> +                           bool written_with_aux);<br>
<br>
</div></div>I think we discussed this before and I forgot the answer. How does this<br>
finish_write function enable future resolves to happen correctly? I'm<br>
trying to understand why prepare_access doesn't do this.<br>
</blockquote></div><br></div><div class="gmail_extra">It avoids an ordering problem.  What usually happens is that you do a bunch of prepare_access calls and then draw and then do a bunch of finish_write calls.  If you did everything in prepare_access, then you could have "prepare" operations interleaved with "finish" operations and one of the "finish" operations could cause a later "prepare" operation to do a resolve even if it isn't needed.  I haven't been able t convince myself that this is actually ever going to be a problem since we do the read-only "prepare" operations first and each of the "finish" operations should happen on unique subresources.  That said, I have convinced myself that it's subtle and confusing enough that it's better to just have two functions.<br><br></div><div class="gmail_extra">--Jason<br></div></div>