turnip: Move sysmem clears to the first subpass that uses them.
authorEmma Anholt <emma@anholt.net>
Mon, 1 Aug 2022 23:45:10 +0000 (16:45 -0700)
committerMarge Bot <emma+marge@anholt.net>
Wed, 16 Aug 2023 16:02:51 +0000 (16:02 +0000)
This is a partial fix for the case where
VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT and the aliased attachment clears
the attachment that was last used in a previous subpass (we have to move
the stores to the last used subpass, as well).

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20994>

src/freedreno/vulkan/tu_cmd_buffer.cc

index d1bd465849acffcfe10e358de47af9418b222b24..8f990af21db90aee8a1510456031f69b82278565 100644 (file)
@@ -1453,21 +1453,6 @@ tu_set_input_attachments(struct tu_cmd_buffer *cmd, const struct tu_subpass *sub
 static void
 tu_emit_renderpass_begin(struct tu_cmd_buffer *cmd)
 {
-   struct tu_cs *cs = &cmd->draw_cs;
-
-   /* Emit sysmem loads and clears, which we do all of in one cond block at the
-    * beginning of the render pass.
-    *
-    * gmem loads and clears happen per-subpass, so we can reuse gmem space
-    * between attachments in separate subpasses.
-    */
-   tu_cond_exec_start(cs, CP_COND_EXEC_0_RENDER_MODE_SYSMEM);
-
-   for (uint32_t i = 0; i < cmd->state.pass->attachment_count; ++i)
-      tu_clear_sysmem_attachment(cmd, cs, i);
-
-   tu_cond_exec_end(cs);
-
    /* We need to re-emit any draw states that are patched in order for them to
     * be correctly added to the per-renderpass patchpoint list, even if they
     * are the same as before.
@@ -3627,8 +3612,28 @@ tu_emit_subpass_begin_gmem(struct tu_cmd_buffer *cmd)
    tu_cond_exec_end(cs); /* CP_COND_EXEC_0_RENDER_MODE_GMEM */
 }
 
-/* emit gmem loads/clears, and mrt/zs/msaa/ubwc state for the subpass that is
+/* Emits sysmem clears that are first used in this subpass. */
+static void
+tu_emit_subpass_begin_sysmem(struct tu_cmd_buffer *cmd)
+{
+   struct tu_cs *cs = &cmd->draw_cs;
+   uint32_t subpass_idx = cmd->state.subpass - cmd->state.pass->subpasses;
+
+   tu_cond_exec_start(cs, CP_COND_EXEC_0_RENDER_MODE_SYSMEM);
+   for (uint32_t i = 0; i < cmd->state.pass->attachment_count; ++i) {
+      struct tu_render_pass_attachment *att = &cmd->state.pass->attachments[i];
+      if (att->clear_mask && att->first_subpass_idx == subpass_idx)
+         tu_clear_sysmem_attachment(cmd, cs, i);
+   }
+   tu_cond_exec_end(cs); /* sysmem */
+}
+
+/* emit loads, clears, and mrt/zs/msaa/ubwc state for the subpass that is
  * starting (either at vkCmdBeginRenderPass2() or vkCmdNextSubpass2())
+ *
+ * Clears and loads have to happen at this point, because with
+ * VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT the loads may depend on the output of
+ * a previous aliased attachment's store.
  */
 static void
 tu_emit_subpass_begin(struct tu_cmd_buffer *cmd)
@@ -3636,6 +3641,8 @@ tu_emit_subpass_begin(struct tu_cmd_buffer *cmd)
    tu_fill_render_pass_state(&cmd->state.vk_rp, cmd->state.pass, cmd->state.subpass);
 
    tu_emit_subpass_begin_gmem(cmd);
+   tu_emit_subpass_begin_sysmem(cmd);
+
    tu6_emit_zs(cmd, cmd->state.subpass, &cmd->draw_cs);
    tu6_emit_mrt(cmd, cmd->state.subpass, &cmd->draw_cs);
    tu6_emit_render_cntl(cmd, cmd->state.subpass, &cmd->draw_cs, false);