anv: Do resolves at end of subpass
authorChad Versace <chad.versace@intel.com>
Thu, 28 Jan 2016 04:42:54 +0000 (20:42 -0800)
committerChad Versace <chad.versace@intel.com>
Thu, 28 Jan 2016 18:49:50 +0000 (10:49 -0800)
src/vulkan/anv_meta_resolve.c
src/vulkan/anv_private.h
src/vulkan/gen7_cmd_buffer.c
src/vulkan/gen8_cmd_buffer.c

index 9969a0e5d883556a2ad1dab2b7c460f9254d3095..ffd41857f1376bb52b1b7bafb8cfb9e4428bea28 100644 (file)
@@ -802,3 +802,64 @@ void anv_CmdResolveImage(
 
    meta_resolve_restore(&state, cmd_buffer);
 }
+
+/**
+ * Emit any needed resolves for the current subpass.
+ */
+void
+anv_cmd_buffer_resolve_subpass(struct anv_cmd_buffer *cmd_buffer)
+{
+   struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
+   struct anv_subpass *subpass = cmd_buffer->state.subpass;
+   struct anv_meta_saved_state saved_state;
+
+   /* FINISHME(perf): Skip clears for resolve attachments.
+    *
+    * From the Vulkan 1.0 spec:
+    *
+    *    If the first use of an attachment in a render pass is as a resolve
+    *    attachment, then the loadOp is effectively ignored as the resolve is
+    *    guaranteed to overwrite all pixels in the render area.
+    */
+
+   if (!subpass->has_resolve)
+      return;
+
+   meta_resolve_save(&saved_state, cmd_buffer);
+
+   for (uint32_t i = 0; i < subpass->color_count; ++i) {
+      uint32_t src_att = subpass->color_attachments[i];
+      uint32_t dest_att = subpass->resolve_attachments[i];
+
+      if (dest_att == VK_ATTACHMENT_UNUSED)
+         continue;
+
+      struct anv_image_view *src_iview = fb->attachments[src_att];
+      struct anv_image_view *dest_iview = fb->attachments[dest_att];
+
+      struct anv_subpass resolve_subpass = {
+         .color_count = 1,
+         .color_attachments = (uint32_t[]) { dest_att },
+         .depth_stencil_attachment = VK_ATTACHMENT_UNUSED,
+      };
+
+      anv_cmd_buffer_set_subpass(cmd_buffer, &resolve_subpass);
+
+      /* Subpass resolves must respect the render area. We can ignore the
+       * render area here because vkCmdBeginRenderPass set the render area
+       * with 3DSTATE_DRAWING_RECTANGLE.
+       *
+       * XXX(chadv): Does the hardware really respect
+       * 3DSTATE_DRAWING_RECTANGLE when draing a 3DPRIM_RECTLIST?
+       */
+      emit_resolve(cmd_buffer,
+          src_iview,
+          &(VkOffset2D) { 0, 0 },
+          dest_iview,
+          &(VkOffset2D) { 0, 0 },
+          &(VkExtent2D) { fb->width, fb->height });
+   }
+
+   cmd_buffer->state.subpass = subpass;
+   meta_resolve_restore(&saved_state, cmd_buffer);
+}
index 6a670190ab9998283fffd7d93cde98de113f74ec..b1d4577f93e72c0b4dffd1ce0b143805ed7b4c1c 100644 (file)
@@ -1277,6 +1277,7 @@ struct anv_state
 anv_cmd_buffer_cs_push_constants(struct anv_cmd_buffer *cmd_buffer);
 
 void anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer *cmd_buffer);
+void anv_cmd_buffer_resolve_subpass(struct anv_cmd_buffer *cmd_buffer);
 
 const struct anv_image_view *
 anv_cmd_buffer_get_depth_stencil_view(const struct anv_cmd_buffer *cmd_buffer);
index f201c151acb2d6e823ccf73beef39b9f77c6907c..609606bdf6af8ea52433a5420e66062b2d1c7f98 100644 (file)
@@ -896,6 +896,7 @@ void genX(CmdNextSubpass)(
 
    assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY);
 
+   anv_cmd_buffer_resolve_subpass(cmd_buffer);
    gen7_cmd_buffer_set_subpass(cmd_buffer, cmd_buffer->state.subpass + 1);
    anv_cmd_buffer_clear_subpass(cmd_buffer);
 }
@@ -905,6 +906,8 @@ void genX(CmdEndRenderPass)(
 {
    ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
 
+   anv_cmd_buffer_resolve_subpass(cmd_buffer);
+
    /* Emit a flushing pipe control at the end of a pass.  This is kind of a
     * hack but it ensures that render targets always actually get written.
     * Eventually, we should do flushing based on image format transitions
index daa049e98e07766ef0751205a412feb43f335be5..4b1c51a8c59678601b86f4bda70d2d232f994ef4 100644 (file)
@@ -972,6 +972,7 @@ void genX(CmdNextSubpass)(
 
    assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY);
 
+   anv_cmd_buffer_resolve_subpass(cmd_buffer);
    genX(cmd_buffer_set_subpass)(cmd_buffer, cmd_buffer->state.subpass + 1);
    anv_cmd_buffer_clear_subpass(cmd_buffer);
 }
@@ -981,6 +982,8 @@ void genX(CmdEndRenderPass)(
 {
    ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
 
+   anv_cmd_buffer_resolve_subpass(cmd_buffer);
+
    /* Emit a flushing pipe control at the end of a pass.  This is kind of a
     * hack but it ensures that render targets always actually get written.
     * Eventually, we should do flushing based on image format transitions