anv: Use blorp for subpass clears
authorJason Ekstrand <jason.ekstrand@intel.com>
Sat, 8 Oct 2016 00:29:36 +0000 (17:29 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Fri, 14 Oct 2016 22:39:41 +0000 (15:39 -0700)
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
Reviewed-by: Topi Pohjolainen <topi.pohjolainen@intel.com>
src/intel/vulkan/anv_blorp.c
src/intel/vulkan/anv_meta_clear.c

index 8577e5f..5361c4b 100644 (file)
@@ -981,6 +981,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 = {
+      .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) {
+      const 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,
+      };
+
+      clear_color_attachment(cmd_buffer, &batch, &clear_att, 1, &clear_rect);
+
+      cmd_state->attachments[a].pending_clear_aspects = 0;
+   }
+
+   const 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,
+      };
+
+      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,
index 6802229..2bc718b 100644 (file)
@@ -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);
-}