[Mesa-dev] [PATCH v4 1/2] anv/cmd_buffer: consider multiview masks for tracking pending clear aspects

Iago Toral itoral at igalia.com
Wed Mar 7 09:33:33 UTC 2018


This patches are still waiting for review.

On Wed, 2018-02-28 at 09:57 +0100, Iago Toral Quiroga wrote:
> When multiview is active a subpass clear may only clear a subset of
> the
> attachment layers. Other subpasses in the same render pass may also
> clear too and we want to honor those clears as well, however, we need
> to
> ensure that we only clear a layer once, on the first subpass that
> uses
> a particular layer (view) of a given attachment.
> 
> This means that when we check if a subpass attachment needs to be
> cleared
> we need to check if all the layers used by that subpass (as indicated
> by
> its view_mask) have already been cleared in previous subpasses or
> not, in
> which case, we must clear any pending layers used by the subpass, and
> only
> those pending.
> 
> v2:
>   - track pending clear views in the attachment state (Jason)
>   - rebased on top of fast-clear rework.
> 
> v3:
>   - rebased on top of subpass rework.
> 
> v4: rebased.
> 
> Fixes:
> dEQP-VK.multiview.readback_implicit_clear.*
> ---
>  src/intel/vulkan/anv_private.h     |  8 ++++
>  src/intel/vulkan/genX_cmd_buffer.c | 87
> ++++++++++++++++++++++++++++++++++++--
>  2 files changed, 92 insertions(+), 3 deletions(-)
> 
> diff --git a/src/intel/vulkan/anv_private.h
> b/src/intel/vulkan/anv_private.h
> index fb4fd19178..352f0483f0 100644
> --- a/src/intel/vulkan/anv_private.h
> +++ b/src/intel/vulkan/anv_private.h
> @@ -1696,6 +1696,14 @@ struct anv_attachment_state {
>     VkClearValue                                 clear_value;
>     bool                                         clear_color_is_zero_
> one;
>     bool                                         clear_color_is_zero;
> +
> +   /* When multiview is active, attachments with a renderpass clear
> +    * operation have their respective layers cleared on the first
> +    * subpass that uses them, and only in that subpass. We keep
> track
> +    * of this using a bitfield to indicate which layers of an
> attachment
> +    * have not been cleared yet when multiview is active.
> +    */
> +   uint32_t                                     pending_clear_views;
>  };
>  
>  /** State tracking for particular pipeline bind point
> diff --git a/src/intel/vulkan/genX_cmd_buffer.c
> b/src/intel/vulkan/genX_cmd_buffer.c
> index ce546249b3..c422ec8e1a 100644
> --- a/src/intel/vulkan/genX_cmd_buffer.c
> +++ b/src/intel/vulkan/genX_cmd_buffer.c
> @@ -1167,6 +1167,8 @@ genX(cmd_buffer_setup_attachments)(struct
> anv_cmd_buffer *cmd_buffer,
>           if (clear_aspects)
>              state->attachments[i].clear_value = begin-
> >pClearValues[i];
>  
> +         state->attachments[i].pending_clear_views = ~0;
> +
>           struct anv_image_view *iview = framebuffer->attachments[i];
>           anv_assert(iview->vk_format == att->format);
>           anv_assert(iview->n_planes == 1);
> @@ -3288,6 +3290,31 @@ cmd_buffer_emit_depth_stencil(struct
> anv_cmd_buffer *cmd_buffer)
>     cmd_buffer->state.hiz_enabled = info.hiz_usage ==
> ISL_AUX_USAGE_HIZ;
>  }
>  
> +/**
> + * This ANDs the view mask of the current subpass with the pending
> clear
> + * views in the attachment to get the mask of views active in the
> subpass
> + * that still need to be cleared.
> + */
> +static inline uint32_t
> +get_multiview_subpass_clear_mask(const struct anv_cmd_state
> *cmd_state,
> +                                 const struct anv_attachment_state
> *att_state)
> +{
> +   return cmd_state->subpass->view_mask & att_state-
> >pending_clear_views;
> +}
> +
> +static inline bool
> +do_first_layer_clear(const struct anv_cmd_state *cmd_state,
> +                     const struct anv_attachment_state *att_state)
> +{
> +   if (!cmd_state->subpass->view_mask)
> +      return true;
> +
> +   uint32_t pending_clear_mask =
> +      get_multiview_subpass_clear_mask(cmd_state, att_state);
> +
> +   return pending_clear_mask & 1;
> +}
> +
>  static void
>  cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer,
>                           uint32_t subpass_id)
> @@ -3326,6 +3353,8 @@ cmd_buffer_begin_subpass(struct anv_cmd_buffer
> *cmd_buffer,
>     VkRect2D render_area = cmd_buffer->state.render_area;
>     struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
>  
> +   bool is_multiview = subpass->view_mask != 0;
> +
>     for (uint32_t i = 0; i < subpass->attachment_count; ++i) {
>        const uint32_t a = subpass->attachments[i].attachment;
>        if (a == VK_ATTACHMENT_UNUSED)
> @@ -3393,7 +3422,8 @@ cmd_buffer_begin_subpass(struct anv_cmd_buffer
> *cmd_buffer,
>           uint32_t base_clear_layer = iview-
> >planes[0].isl.base_array_layer;
>           uint32_t clear_layer_count = fb->layers;
>  
> -         if (att_state->fast_clear) {
> +         if (att_state->fast_clear &&
> +             do_first_layer_clear(cmd_state, att_state)) {
>              /* We only support fast-clears on the first layer */
>              assert(iview->planes[0].isl.base_level == 0);
>              assert(iview->planes[0].isl.base_array_layer == 0);
> @@ -3402,6 +3432,8 @@ cmd_buffer_begin_subpass(struct anv_cmd_buffer
> *cmd_buffer,
>                               0, 0, 1, ISL_AUX_OP_FAST_CLEAR, false);
>              base_clear_layer++;
>              clear_layer_count--;
> +            if (is_multiview)
> +               att_state->pending_clear_views &= ~1;
>  
>              genX(copy_fast_clear_dwords)(cmd_buffer, att_state-
> >color.state,
>                                           image,
> VK_IMAGE_ASPECT_COLOR_BIT,
> @@ -3423,7 +3455,39 @@ cmd_buffer_begin_subpass(struct anv_cmd_buffer
> *cmd_buffer,
>              }
>           }
>  
> -         if (clear_layer_count > 0) {
> +         /* From the VkFramebufferCreateInfo spec:
> +          *
> +          * "If the render pass uses multiview, then layers must be
> one and each
> +          *  attachment requires a number of layers that is greater
> than the
> +          *  maximum bit index set in the view mask in the subpasses
> in which it
> +          *  is used."
> +          *
> +          * So if multiview is active we ignore the number of layers
> in the
> +          * framebuffer and instead we honor the view mask from the
> subpass.
> +          */
> +         if (is_multiview) {
> +            assert(image->n_planes == 1);
> +            uint32_t pending_clear_mask =
> +               get_multiview_subpass_clear_mask(cmd_state,
> att_state);
> +
> +            uint32_t layer_idx;
> +            for_each_bit(layer_idx, pending_clear_mask) {
> +               uint32_t layer =
> +                  iview->planes[0].isl.base_array_layer + layer_idx;
> +
> +               anv_image_clear_color(cmd_buffer, image,
> +                                     VK_IMAGE_ASPECT_COLOR_BIT,
> +                                     att_state->aux_usage,
> +                                     iview->planes[0].isl.format,
> +                                     iview->planes[0].isl.swizzle,
> +                                     iview-
> >planes[0].isl.base_level,
> +                                     layer, 1,
> +                                     render_area,
> +                                     vk_to_isl_color(att_state-
> >clear_value.color));
> +
> +               att_state->pending_clear_views &= ~(1 << layer_idx);
> +            }
> +         } else if (clear_layer_count > 0) {
>              assert(image->n_planes == 1);
>              anv_image_clear_color(cmd_buffer, image,
> VK_IMAGE_ASPECT_COLOR_BIT,
>                                    att_state->aux_usage,
> @@ -3525,7 +3589,24 @@ cmd_buffer_begin_subpass(struct anv_cmd_buffer
> *cmd_buffer,
>           }
>        }
>  
> -      att_state->pending_clear_aspects = 0;
> +      /* If multiview is enabled, then we are only done clearing
> when we no
> +       * longer have pending layers to clear, or when we have
> processed the
> +       * last subpass that uses this attachment.
> +       */
> +      if (!is_multiview) {
> +         att_state->pending_clear_aspects = 0;
> +      } else if (att_state->pending_clear_views == 0) {
> +         att_state->pending_clear_aspects = 0;
> +      } else {
> +         uint32_t last_subpass_idx =
> +            cmd_state->pass->attachments[a].last_subpass_idx;
> +         const struct anv_subpass *last_subpass =
> +            &cmd_state->pass->subpasses[last_subpass_idx];
> +         if (last_subpass == cmd_state->subpass) {
> +            att_state->pending_clear_aspects = 0;
> +         }
> +      }
> +
>        att_state->pending_load_aspects = 0;
>     }
>  
> -- 
> 2.14.1
> 
> 


More information about the mesa-dev mailing list