v3dv: compute subpass ranges for attachments at render pass creation time

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c
index a312094..e07c3d2 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -613,55 +613,10 @@
    }
 }
 
-/* Identifies the first and last subpasses that use each attachment in
- * the current render pass.
- *
- * FIXME: consider doing this at render pass creation time and store it
- * in the render pass data.
- */
-static void
-cmd_buffer_find_subpass_range_for_attachments(struct v3dv_cmd_buffer *cmd_buffer)
-{
-   struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;
-   const struct v3dv_render_pass *pass = state->pass;
-
-   for (uint32_t i = 0; i < pass->attachment_count; i++) {
-      state->attachments[i].first_subpass = pass->subpass_count - 1;
-      state->attachments[i].last_subpass = 0;
-   }
-
-   for (uint32_t i = 0; i < pass->subpass_count; i++) {
-      const struct v3dv_subpass *subpass = &pass->subpasses[i];
-
-      for (uint32_t j = 0; j < subpass->color_count; j++) {
-         uint32_t attachment_idx = subpass->color_attachments[j].attachment;
-         if (attachment_idx == VK_ATTACHMENT_UNUSED)
-            continue;
-
-         if (i < state->attachments[attachment_idx].first_subpass)
-            state->attachments[attachment_idx].first_subpass = i;
-         if (i > state->attachments[attachment_idx].last_subpass)
-            state->attachments[attachment_idx].last_subpass = i;
-      }
-
-      uint32_t ds_attachment_idx = subpass->ds_attachment.attachment;
-      if (ds_attachment_idx != VK_ATTACHMENT_UNUSED) {
-         if (i < state->attachments[ds_attachment_idx].first_subpass)
-            state->attachments[ds_attachment_idx].first_subpass = i;
-         if (i > state->attachments[ds_attachment_idx].last_subpass)
-            state->attachments[ds_attachment_idx].last_subpass = i;
-      }
-
-      /* FIXME: input/resolve attachments */
-   }
-}
-
 static void
 cmd_buffer_init_render_pass_attachment_state(struct v3dv_cmd_buffer *cmd_buffer,
                                              const VkRenderPassBeginInfo *pRenderPassBegin)
 {
-   cmd_buffer_find_subpass_range_for_attachments(cmd_buffer);
-
    cmd_buffer_state_set_clear_values(cmd_buffer,
                                      pRenderPassBegin->clearValueCount,
                                      pRenderPassBegin->pClearValues);
@@ -801,8 +756,8 @@
 {
    const struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;
    const struct v3dv_framebuffer *framebuffer = state->framebuffer;
-   const struct v3dv_subpass *subpass =
-      &state->pass->subpasses[state->subpass_idx];
+   const struct v3dv_render_pass *pass = state->pass;
+   const struct v3dv_subpass *subpass = &pass->subpasses[state->subpass_idx];
 
    for (uint32_t i = 0; i < subpass->color_count; i++) {
       uint32_t attachment_idx = subpass->color_attachments[i].attachment;
@@ -813,9 +768,6 @@
       const struct v3dv_render_pass_attachment *attachment =
          &state->pass->attachments[attachment_idx];
 
-      const struct v3dv_cmd_buffer_attachment_state *attachment_state =
-         &state->attachments[attachment_idx];
-
       /* According to the Vulkan spec:
        *
        *    "The load operation for each sample in an attachment happens before
@@ -827,9 +779,9 @@
        * After that, we always want to load so we don't lose any rendering done
        * by a previous subpass to the same attachment.
        */
-      assert(state->job->first_subpass >= attachment_state->first_subpass);
+      assert(state->job->first_subpass >= attachment->first_subpass);
       bool needs_load =
-         state->job->first_subpass > attachment_state->first_subpass ||
+         state->job->first_subpass > attachment->first_subpass ||
          attachment->desc.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD;
 
       if (needs_load) {
@@ -843,12 +795,10 @@
    if (ds_attachment_idx != VK_ATTACHMENT_UNUSED) {
       const struct v3dv_render_pass_attachment *ds_attachment =
          &state->pass->attachments[ds_attachment_idx];
-      const struct v3dv_cmd_buffer_attachment_state *ds_attachment_state =
-         &state->attachments[ds_attachment_idx];
 
-      assert(state->job->first_subpass >= ds_attachment_state->first_subpass);
+      assert(state->job->first_subpass >= ds_attachment->first_subpass);
       bool needs_load =
-         state->job->first_subpass > ds_attachment_state->first_subpass ||
+         state->job->first_subpass > ds_attachment->first_subpass ||
          ds_attachment->desc.loadOp == VK_ATTACHMENT_LOAD_OP_LOAD;
 
       if (needs_load) {
@@ -920,21 +870,18 @@
       const struct v3dv_render_pass_attachment *attachment =
          &state->pass->attachments[attachment_idx];
 
-      const struct v3dv_cmd_buffer_attachment_state *attachment_state =
-         &state->attachments[attachment_idx];
-
-      assert(state->job->first_subpass >= attachment_state->first_subpass);
-      assert(state->subpass_idx >= attachment_state->first_subpass);
-      assert(state->subpass_idx <= attachment_state->last_subpass);
+      assert(state->job->first_subpass >= attachment->first_subpass);
+      assert(state->subpass_idx >= attachment->first_subpass);
+      assert(state->subpass_idx <= attachment->last_subpass);
 
       /* Only clear once on the first subpass that uses the attachment */
       bool needs_clear =
-         state->job->first_subpass == attachment_state->first_subpass &&
+         state->job->first_subpass == attachment->first_subpass &&
          attachment->desc.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR;
 
       /* Skip the last store if it is not required  */
       bool needs_store =
-         state->subpass_idx < attachment_state->last_subpass ||
+         state->subpass_idx < attachment->last_subpass ||
          attachment->desc.storeOp == VK_ATTACHMENT_STORE_OP_STORE ||
          needs_clear;
 
@@ -965,21 +912,19 @@
    if (ds_attachment_idx != VK_ATTACHMENT_UNUSED) {
       const struct v3dv_render_pass_attachment *ds_attachment =
          &state->pass->attachments[ds_attachment_idx];
-      const struct v3dv_cmd_buffer_attachment_state *ds_attachment_state =
-         &state->attachments[ds_attachment_idx];
 
-      assert(state->job->first_subpass >= ds_attachment_state->first_subpass);
-      assert(state->subpass_idx >= ds_attachment_state->first_subpass);
-      assert(state->subpass_idx <= ds_attachment_state->last_subpass);
+      assert(state->job->first_subpass >= ds_attachment->first_subpass);
+      assert(state->subpass_idx >= ds_attachment->first_subpass);
+      assert(state->subpass_idx <= ds_attachment->last_subpass);
 
       /* Only clear once on the first subpass that uses the attachment */
       needs_ds_clear =
-         state->job->first_subpass == ds_attachment_state->first_subpass &&
+         state->job->first_subpass == ds_attachment->first_subpass &&
          ds_attachment->desc.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR;
 
       /* Skip the last store if it is not required  */
       bool needs_ds_store =
-         state->subpass_idx < ds_attachment_state->last_subpass ||
+         state->subpass_idx < ds_attachment->last_subpass ||
          ds_attachment->desc.storeOp == VK_ATTACHMENT_STORE_OP_STORE ||
          needs_ds_clear;
 
diff --git a/src/broadcom/vulkan/v3dv_pass.c b/src/broadcom/vulkan/v3dv_pass.c
index 7ec389e..a84ff73 100644
--- a/src/broadcom/vulkan/v3dv_pass.c
+++ b/src/broadcom/vulkan/v3dv_pass.c
@@ -32,6 +32,41 @@
           (desc->pDepthStencilAttachment != NULL);
 }
 
+static void
+pass_find_subpass_range_for_attachments(struct v3dv_render_pass *pass)
+{
+   for (uint32_t i = 0; i < pass->attachment_count; i++) {
+      pass->attachments[i].first_subpass = pass->subpass_count - 1;
+      pass->attachments[i].last_subpass = 0;
+   }
+
+   for (uint32_t i = 0; i < pass->subpass_count; i++) {
+      const struct v3dv_subpass *subpass = &pass->subpasses[i];
+
+      for (uint32_t j = 0; j < subpass->color_count; j++) {
+         uint32_t attachment_idx = subpass->color_attachments[j].attachment;
+         if (attachment_idx == VK_ATTACHMENT_UNUSED)
+            continue;
+
+         if (i < pass->attachments[attachment_idx].first_subpass)
+            pass->attachments[attachment_idx].first_subpass = i;
+         if (i > pass->attachments[attachment_idx].last_subpass)
+            pass->attachments[attachment_idx].last_subpass = i;
+      }
+
+      uint32_t ds_attachment_idx = subpass->ds_attachment.attachment;
+      if (ds_attachment_idx != VK_ATTACHMENT_UNUSED) {
+         if (i < pass->attachments[ds_attachment_idx].first_subpass)
+            pass->attachments[ds_attachment_idx].first_subpass = i;
+         if (i > pass->attachments[ds_attachment_idx].last_subpass)
+            pass->attachments[ds_attachment_idx].last_subpass = i;
+      }
+
+      /* FIXME: input/resolve attachments */
+   }
+}
+
+
 VkResult
 v3dv_CreateRenderPass(VkDevice _device,
                       const VkRenderPassCreateInfo *pCreateInfo,
@@ -137,6 +172,8 @@
       }
    }
 
+   pass_find_subpass_range_for_attachments(pass);
+
    /* FIXME: handle subpass dependencies */
 
    *pRenderPass = v3dv_render_pass_to_handle(pass);
diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h
index d286cb8..0cd0c52 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -358,6 +358,8 @@
 
 struct v3dv_render_pass_attachment {
    VkAttachmentDescription desc;
+   uint32_t first_subpass;
+   uint32_t last_subpass;
 };
 
 struct v3dv_render_pass {
@@ -412,8 +414,6 @@
 
 struct v3dv_cmd_buffer_attachment_state {
    union v3dv_clear_value clear_value;
-   uint32_t first_subpass;
-   uint32_t last_subpass;
 };
 
 struct v3dv_viewport_state {