[Mesa-dev] [PATCH 18/22] anv: Use blorp for subpass clears

Pohjolainen, Topi topi.pohjolainen at gmail.com
Wed Oct 12 09:40:49 UTC 2016


On Fri, Oct 07, 2016 at 09:41:16PM -0700, Jason Ekstrand wrote:
> Signed-off-by: Jason Ekstrand <jason at jlekstrand.net>
> ---
>  src/intel/vulkan/anv_blorp.c      |  81 +++++++++++
>  src/intel/vulkan/anv_meta_clear.c | 298 --------------------------------------
>  2 files changed, 81 insertions(+), 298 deletions(-)
> 
> diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c
> index 4279f62..968c887 100644
> --- a/src/intel/vulkan/anv_blorp.c
> +++ b/src/intel/vulkan/anv_blorp.c
> @@ -982,6 +982,87 @@ void anv_CmdClearAttachments(
>     blorp_batch_finish(&batch);
>  }
>  
> +static bool
> +subpass_needs_clear(const struct anv_cmd_buffer *cmd_buffer)
> +{
> +   const struct anv_cmd_state *cmd_state = &cmd_buffer->state;
> +   uint32_t ds = cmd_state->subpass->depth_stencil_attachment;
> +
> +   for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) {
> +      uint32_t a = cmd_state->subpass->color_attachments[i];
> +      if (cmd_state->attachments[a].pending_clear_aspects) {
> +         return true;
> +      }
> +   }
> +
> +   if (ds != VK_ATTACHMENT_UNUSED &&
> +       cmd_state->attachments[ds].pending_clear_aspects) {
> +      return true;
> +   }
> +
> +   return false;
> +}
> +
> +void
> +anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer *cmd_buffer)
> +{
> +   const struct anv_cmd_state *cmd_state = &cmd_buffer->state;
> +
> +   if (!subpass_needs_clear(cmd_buffer))
> +      return;
> +
> +   /* Because this gets called within a render pass, we tell blorp not to
> +    * trash our depth and stencil buffers.
> +    */
> +   struct blorp_batch batch;
> +   blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer,
> +                    BLORP_BATCH_NO_EMIT_DEPTH_STENCIL);
> +
> +   VkClearRect clear_rect = {

Could be const.

> +      .rect = cmd_buffer->state.render_area,
> +      .baseArrayLayer = 0,
> +      .layerCount = cmd_buffer->state.framebuffer->layers,
> +   };
> +
> +   for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) {
> +      uint32_t a = cmd_state->subpass->color_attachments[i];

As well.

> +
> +      if (!cmd_state->attachments[a].pending_clear_aspects)
> +         continue;
> +
> +      assert(cmd_state->attachments[a].pending_clear_aspects ==
> +             VK_IMAGE_ASPECT_COLOR_BIT);
> +
> +      VkClearAttachment clear_att = {

And this.

> +         .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
> +         .colorAttachment = i, /* Use attachment index relative to subpass */
> +         .clearValue = cmd_state->attachments[a].clear_value,
> +      };
> +
> +      clear_color_attachment(cmd_buffer, &batch, &clear_att, 1, &clear_rect);
> +
> +      cmd_state->attachments[a].pending_clear_aspects = 0;
> +   }
> +
> +   uint32_t ds = cmd_state->subpass->depth_stencil_attachment;

And this.

> +
> +   if (ds != VK_ATTACHMENT_UNUSED &&
> +       cmd_state->attachments[ds].pending_clear_aspects) {
> +
> +      VkClearAttachment clear_att = {

And this.

All in all looks quite a bit simpler:

Reviewed-by: Topi Pohjolainen <topi.pohjolainen at intel.com>

> +         .aspectMask = cmd_state->attachments[ds].pending_clear_aspects,
> +         .clearValue = cmd_state->attachments[ds].clear_value,
> +      };
> +
> +      clear_depth_stencil_attachment(cmd_buffer, &batch,
> +                                     &clear_att, 1, &clear_rect);
> +
> +      cmd_state->attachments[ds].pending_clear_aspects = 0;
> +   }
> +
> +   blorp_batch_finish(&batch);
> +}
> +
>  static void
>  resolve_image(struct blorp_batch *batch,
>                const struct anv_image *src_image,
> diff --git a/src/intel/vulkan/anv_meta_clear.c b/src/intel/vulkan/anv_meta_clear.c
> index 6802229..2bc718b 100644
> --- a/src/intel/vulkan/anv_meta_clear.c
> +++ b/src/intel/vulkan/anv_meta_clear.c
> @@ -41,26 +41,6 @@ struct depthstencil_clear_vattrs {
>  };
>  
>  static void
> -meta_clear_begin(struct anv_meta_saved_state *saved_state,
> -                 struct anv_cmd_buffer *cmd_buffer)
> -{
> -   anv_meta_save(saved_state, cmd_buffer,
> -                 (1 << VK_DYNAMIC_STATE_VIEWPORT) |
> -                 (1 << VK_DYNAMIC_STATE_STENCIL_REFERENCE) |
> -                 (1 << VK_DYNAMIC_STATE_STENCIL_WRITE_MASK));
> -
> -   /* Avoid uploading more viewport states than necessary */
> -   cmd_buffer->state.dynamic.viewport.count = 0;
> -}
> -
> -static void
> -meta_clear_end(struct anv_meta_saved_state *saved_state,
> -               struct anv_cmd_buffer *cmd_buffer)
> -{
> -   anv_meta_restore(saved_state, cmd_buffer);
> -}
> -
> -static void
>  build_color_shaders(struct nir_shader **out_vs,
>                      struct nir_shader **out_fs,
>                      uint32_t frag_output)
> @@ -337,80 +317,6 @@ anv_device_finish_meta_clear_state(struct anv_device *device)
>  }
>  
>  static void
> -emit_color_clear(struct anv_cmd_buffer *cmd_buffer,
> -                 const VkClearAttachment *clear_att,
> -                 const VkClearRect *clear_rect)
> -{
> -   struct anv_device *device = cmd_buffer->device;
> -   const struct anv_subpass *subpass = cmd_buffer->state.subpass;
> -   const struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
> -   const uint32_t subpass_att = clear_att->colorAttachment;
> -   const uint32_t pass_att = subpass->color_attachments[subpass_att];
> -   const struct anv_image_view *iview = fb->attachments[pass_att];
> -   const uint32_t samples = iview->image->samples;
> -   const uint32_t samples_log2 = ffs(samples) - 1;
> -   struct anv_pipeline *pipeline =
> -      device->meta_state.clear[samples_log2].color_pipelines[subpass_att];
> -   VkClearColorValue clear_value = clear_att->clearValue.color;
> -
> -   VkCommandBuffer cmd_buffer_h = anv_cmd_buffer_to_handle(cmd_buffer);
> -   VkPipeline pipeline_h = anv_pipeline_to_handle(pipeline);
> -
> -   assert(samples_log2 < ARRAY_SIZE(device->meta_state.clear));
> -   assert(clear_att->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT);
> -   assert(clear_att->colorAttachment < subpass->color_count);
> -
> -   const struct color_clear_vattrs vertex_data[3] = {
> -      {
> -         .vue_header = { 0 },
> -         .position = {
> -            clear_rect->rect.offset.x,
> -            clear_rect->rect.offset.y,
> -         },
> -         .color = clear_value,
> -      },
> -      {
> -         .vue_header = { 0 },
> -         .position = {
> -            clear_rect->rect.offset.x + clear_rect->rect.extent.width,
> -            clear_rect->rect.offset.y,
> -         },
> -         .color = clear_value,
> -      },
> -      {
> -         .vue_header = { 0 },
> -         .position = {
> -            clear_rect->rect.offset.x + clear_rect->rect.extent.width,
> -            clear_rect->rect.offset.y + clear_rect->rect.extent.height,
> -         },
> -         .color = clear_value,
> -      },
> -   };
> -
> -   struct anv_state state =
> -      anv_cmd_buffer_emit_dynamic(cmd_buffer, vertex_data, sizeof(vertex_data), 16);
> -
> -   struct anv_buffer vertex_buffer = {
> -      .device = device,
> -      .size = sizeof(vertex_data),
> -      .bo = &device->dynamic_state_block_pool.bo,
> -      .offset = state.offset,
> -   };
> -
> -   ANV_CALL(CmdBindVertexBuffers)(cmd_buffer_h, 0, 1,
> -      (VkBuffer[]) { anv_buffer_to_handle(&vertex_buffer) },
> -      (VkDeviceSize[]) { 0 });
> -
> -   if (cmd_buffer->state.pipeline != pipeline) {
> -      ANV_CALL(CmdBindPipeline)(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
> -                                pipeline_h);
> -   }
> -
> -   ANV_CALL(CmdDraw)(cmd_buffer_h, 3, 1, 0, 0);
> -}
> -
> -
> -static void
>  build_depthstencil_shader(struct nir_shader **out_vs)
>  {
>     nir_builder vs_b;
> @@ -503,111 +409,6 @@ create_depthstencil_pipeline(struct anv_device *device,
>                            /*use_repclear*/ true, pipeline);
>  }
>  
> -static void
> -emit_depthstencil_clear(struct anv_cmd_buffer *cmd_buffer,
> -                        const VkClearAttachment *clear_att,
> -                        const VkClearRect *clear_rect)
> -{
> -   struct anv_device *device = cmd_buffer->device;
> -   struct anv_meta_state *meta_state = &device->meta_state;
> -   const struct anv_subpass *subpass = cmd_buffer->state.subpass;
> -   const struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
> -   const uint32_t pass_att = subpass->depth_stencil_attachment;
> -   const struct anv_image_view *iview = fb->attachments[pass_att];
> -   const uint32_t samples = iview->image->samples;
> -   const uint32_t samples_log2 = ffs(samples) - 1;
> -   VkClearDepthStencilValue clear_value = clear_att->clearValue.depthStencil;
> -   VkImageAspectFlags aspects = clear_att->aspectMask;
> -
> -   VkCommandBuffer cmd_buffer_h = anv_cmd_buffer_to_handle(cmd_buffer);
> -
> -   assert(samples_log2 < ARRAY_SIZE(meta_state->clear));
> -   assert(aspects == VK_IMAGE_ASPECT_DEPTH_BIT ||
> -          aspects == VK_IMAGE_ASPECT_STENCIL_BIT ||
> -          aspects == (VK_IMAGE_ASPECT_DEPTH_BIT |
> -                      VK_IMAGE_ASPECT_STENCIL_BIT));
> -   assert(pass_att != VK_ATTACHMENT_UNUSED);
> -
> -   const struct depthstencil_clear_vattrs vertex_data[3] = {
> -      {
> -         .vue_header = { 0 },
> -         .position = {
> -            clear_rect->rect.offset.x,
> -            clear_rect->rect.offset.y,
> -         },
> -      },
> -      {
> -         .vue_header = { 0 },
> -         .position = {
> -            clear_rect->rect.offset.x + clear_rect->rect.extent.width,
> -            clear_rect->rect.offset.y,
> -         },
> -      },
> -      {
> -         .vue_header = { 0 },
> -         .position = {
> -            clear_rect->rect.offset.x + clear_rect->rect.extent.width,
> -            clear_rect->rect.offset.y + clear_rect->rect.extent.height,
> -         },
> -      },
> -   };
> -
> -   struct anv_state state =
> -      anv_cmd_buffer_emit_dynamic(cmd_buffer, vertex_data, sizeof(vertex_data), 16);
> -
> -   struct anv_buffer vertex_buffer = {
> -      .device = device,
> -      .size = sizeof(vertex_data),
> -      .bo = &device->dynamic_state_block_pool.bo,
> -      .offset = state.offset,
> -   };
> -
> -   ANV_CALL(CmdSetViewport)(cmd_buffer_h, 0, 1,
> -      (VkViewport[]) {
> -         {
> -            .x = 0,
> -            .y = 0,
> -            .width = fb->width,
> -            .height = fb->height,
> -
> -            /* Ignored when clearing only stencil. */
> -            .minDepth = clear_value.depth,
> -            .maxDepth = clear_value.depth,
> -         },
> -      });
> -
> -   if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
> -      ANV_CALL(CmdSetStencilReference)(cmd_buffer_h, VK_STENCIL_FACE_FRONT_BIT,
> -                                       clear_value.stencil);
> -   }
> -
> -   ANV_CALL(CmdBindVertexBuffers)(cmd_buffer_h, 0, 1,
> -      (VkBuffer[]) { anv_buffer_to_handle(&vertex_buffer) },
> -      (VkDeviceSize[]) { 0 });
> -
> -   struct anv_pipeline *pipeline;
> -   switch (aspects) {
> -   case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT:
> -      pipeline = meta_state->clear[samples_log2].depthstencil_pipeline;
> -      break;
> -   case VK_IMAGE_ASPECT_DEPTH_BIT:
> -      pipeline = meta_state->clear[samples_log2].depth_only_pipeline;
> -      break;
> -   case VK_IMAGE_ASPECT_STENCIL_BIT:
> -      pipeline = meta_state->clear[samples_log2].stencil_only_pipeline;
> -      break;
> -   default:
> -      unreachable("expected depth or stencil aspect");
> -   }
> -
> -   if (cmd_buffer->state.pipeline != pipeline) {
> -      ANV_CALL(CmdBindPipeline)(cmd_buffer_h, VK_PIPELINE_BIND_POINT_GRAPHICS,
> -                                anv_pipeline_to_handle(pipeline));
> -   }
> -
> -   ANV_CALL(CmdDraw)(cmd_buffer_h, 3, 1, 0, 0);
> -}
> -
>  VkResult
>  anv_device_init_meta_clear_state(struct anv_device *device)
>  {
> @@ -652,102 +453,3 @@ fail:
>     anv_device_finish_meta_clear_state(device);
>     return res;
>  }
> -
> -/**
> - * The parameters mean that same as those in vkCmdClearAttachments.
> - */
> -static void
> -emit_clear(struct anv_cmd_buffer *cmd_buffer,
> -           const VkClearAttachment *clear_att,
> -           const VkClearRect *clear_rect)
> -{
> -   if (clear_att->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
> -      emit_color_clear(cmd_buffer, clear_att, clear_rect);
> -   } else {
> -      assert(clear_att->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT |
> -                                      VK_IMAGE_ASPECT_STENCIL_BIT));
> -      emit_depthstencil_clear(cmd_buffer, clear_att, clear_rect);
> -   }
> -}
> -
> -static bool
> -subpass_needs_clear(const struct anv_cmd_buffer *cmd_buffer)
> -{
> -   const struct anv_cmd_state *cmd_state = &cmd_buffer->state;
> -   uint32_t ds = cmd_state->subpass->depth_stencil_attachment;
> -
> -   for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) {
> -      uint32_t a = cmd_state->subpass->color_attachments[i];
> -      if (cmd_state->attachments[a].pending_clear_aspects) {
> -         return true;
> -      }
> -   }
> -
> -   if (ds != VK_ATTACHMENT_UNUSED &&
> -       cmd_state->attachments[ds].pending_clear_aspects) {
> -      return true;
> -   }
> -
> -   return false;
> -}
> -
> -/**
> - * Emit any pending attachment clears for the current subpass.
> - *
> - * @see anv_attachment_state::pending_clear_aspects
> - */
> -void
> -anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer *cmd_buffer)
> -{
> -   struct anv_cmd_state *cmd_state = &cmd_buffer->state;
> -   struct anv_meta_saved_state saved_state;
> -
> -   if (!subpass_needs_clear(cmd_buffer))
> -      return;
> -
> -   meta_clear_begin(&saved_state, cmd_buffer);
> -
> -   if (cmd_state->framebuffer->layers > 1)
> -      anv_finishme("clearing multi-layer framebuffer");
> -
> -   VkClearRect clear_rect = {
> -      .rect = cmd_state->render_area,
> -      .baseArrayLayer = 0,
> -      .layerCount = 1, /* FINISHME: clear multi-layer framebuffer */
> -   };
> -
> -   for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) {
> -      uint32_t a = cmd_state->subpass->color_attachments[i];
> -
> -      if (!cmd_state->attachments[a].pending_clear_aspects)
> -         continue;
> -
> -      assert(cmd_state->attachments[a].pending_clear_aspects ==
> -             VK_IMAGE_ASPECT_COLOR_BIT);
> -
> -      VkClearAttachment clear_att = {
> -         .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
> -         .colorAttachment = i, /* Use attachment index relative to subpass */
> -         .clearValue = cmd_state->attachments[a].clear_value,
> -      };
> -
> -      emit_clear(cmd_buffer, &clear_att, &clear_rect);
> -      cmd_state->attachments[a].pending_clear_aspects = 0;
> -   }
> -
> -   uint32_t ds = cmd_state->subpass->depth_stencil_attachment;
> -
> -   if (ds != VK_ATTACHMENT_UNUSED &&
> -       cmd_state->attachments[ds].pending_clear_aspects) {
> -
> -      VkClearAttachment clear_att = {
> -         .aspectMask = cmd_state->attachments[ds].pending_clear_aspects,
> -         .clearValue = cmd_state->attachments[ds].clear_value,
> -      };
> -
> -      emit_clear(cmd_buffer, &clear_att, &clear_rect);
> -      cmd_state->attachments[ds].pending_clear_aspects = 0;
> -   }
> -
> -   meta_clear_end(&saved_state, cmd_buffer);
> -}
> -- 
> 2.5.0.400.gff86faf
> 
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list