v3dv: fix subpass tracking in the command buffer state

When we create a new job for a new subpass, we might have to finish
the current job for the previous subpass, so it is important that we
we don't get ahead of ourselves and increment the current subpass index
in the command buffer state until we are really done finishing the
previous job.

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 d1c4878..fe53ead 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -72,7 +72,7 @@
 }
 
 static void
-subpass_start(struct v3dv_cmd_buffer *cmd_buffer);
+subpass_start(struct v3dv_cmd_buffer *cmd_buffer, uint32_t subpass_idx);
 
 static void
 subpass_finish(struct v3dv_cmd_buffer *cmd_buffer);
@@ -397,13 +397,13 @@
 
 struct v3dv_job *
 v3dv_cmd_buffer_start_job(struct v3dv_cmd_buffer *cmd_buffer,
-                          bool is_subpass_start)
+                          int32_t subpass_idx)
 {
    /* Don't create a new job if we can merge the current subpass into
     * the current job.
     */
    if (cmd_buffer->state.pass &&
-       is_subpass_start &&
+       subpass_idx != -1 &&
        cmd_buffer_can_merge_subpass(cmd_buffer)) {
       cmd_buffer->state.job->is_subpass_finish = false;
       return cmd_buffer->state.job;
@@ -442,9 +442,10 @@
     * and stores.
     */
    if (cmd_buffer->state.pass)
-      job->first_subpass = cmd_buffer->state.subpass_idx;
+      job->first_subpass = subpass_idx;
 
    cmd_buffer->state.job = job;
+
    return job;
 }
 
@@ -759,8 +760,7 @@
    state->render_area = pRenderPassBegin->renderArea;
 
    /* Setup for first subpass */
-   state->subpass_idx = 0;
-   subpass_start(cmd_buffer);
+   subpass_start(cmd_buffer, 0);
 }
 
 void
@@ -775,8 +775,7 @@
    subpass_finish(cmd_buffer);
 
    /* Start the next subpass */
-   state->subpass_idx++;
-   subpass_start(cmd_buffer);
+   subpass_start(cmd_buffer, state->subpass_idx + 1);
 }
 
 void
@@ -1390,13 +1389,19 @@
 }
 
 static void
-subpass_start(struct v3dv_cmd_buffer *cmd_buffer)
+subpass_start(struct v3dv_cmd_buffer *cmd_buffer, uint32_t subpass_idx)
 {
-   const struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;
+   struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;
+   assert(subpass_idx < state->pass->subpass_count);
 
-   assert(state->subpass_idx < state->pass->subpass_count);
+   /* Starting a new job can trigger a finish of the current one, so don't
+    * change the command buffer state for the new job until we are done creating
+    * the new job.
+    */
+   struct v3dv_job *job =
+   v3dv_cmd_buffer_start_job(cmd_buffer, subpass_idx);
 
-   struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, true);
+   state->subpass_idx = subpass_idx;
 
    /* If we are starting a new job we need to setup binning. */
    if (job->first_subpass == state->subpass_idx)
diff --git a/src/broadcom/vulkan/v3dv_meta_copy.c b/src/broadcom/vulkan/v3dv_meta_copy.c
index 6c18b17..17dd576 100644
--- a/src/broadcom/vulkan/v3dv_meta_copy.c
+++ b/src/broadcom/vulkan/v3dv_meta_copy.c
@@ -680,7 +680,7 @@
    framebuffer.max_x_supertile = max_render_x / supertile_w_in_pixels;
    framebuffer.max_y_supertile = max_render_y / supertile_h_in_pixels;
 
-   struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, false);
+   struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, -1);
    v3dv_cmd_buffer_start_frame(cmd_buffer, &framebuffer.fb);
 
    v3dv_job_emit_binning_flush(job);
@@ -834,7 +834,7 @@
    framebuffer.max_x_supertile = max_render_x / supertile_w_in_pixels;
    framebuffer.max_y_supertile = max_render_y / supertile_h_in_pixels;
 
-   struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, false);
+   struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, -1);
    v3dv_cmd_buffer_start_frame(cmd_buffer, &framebuffer.fb);
 
    v3dv_job_emit_binning_flush(job);
@@ -966,7 +966,7 @@
          setup_framebuffer_params(&framebuffer, width, height, 1,
                                   internal_bpp, internal_type);
 
-         struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, false);
+         struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, -1);
          v3dv_cmd_buffer_start_frame(cmd_buffer, &framebuffer.fb);
          v3dv_job_emit_binning_flush(job);
 
@@ -1171,7 +1171,7 @@
       setup_framebuffer_for_pixel_count(&framebuffer, num_items,
                                         internal_bpp, internal_type);
 
-      job = v3dv_cmd_buffer_start_job(cmd_buffer, false);
+      job = v3dv_cmd_buffer_start_job(cmd_buffer, -1);
       v3dv_cmd_buffer_start_frame(cmd_buffer, &framebuffer.fb);
 
       v3dv_job_emit_binning_flush(job);
@@ -1327,7 +1327,7 @@
       setup_framebuffer_for_pixel_count(&framebuffer, num_items,
                                         internal_bpp, internal_type);
 
-      struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, false);
+      struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, -1);
       v3dv_cmd_buffer_start_frame(cmd_buffer, &framebuffer.fb);
 
       v3dv_job_emit_binning_flush(job);
@@ -1531,7 +1531,7 @@
    framebuffer.max_x_supertile = max_render_x / supertile_w_in_pixels;
    framebuffer.max_y_supertile = max_render_y / supertile_h_in_pixels;
 
-   struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, false);
+   struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, -1);
    v3dv_cmd_buffer_start_frame(cmd_buffer, &framebuffer.fb);
 
    v3dv_job_emit_binning_flush(job);
diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h
index fa55127..9ceb4b9 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -633,7 +633,7 @@
 };
 
 struct v3dv_job *v3dv_cmd_buffer_start_job(struct v3dv_cmd_buffer *cmd_buffer,
-                                           bool is_subpass_finish);
+                                           int32_t subpass_idx);
 void v3dv_cmd_buffer_finish_job(struct v3dv_cmd_buffer *cmd_buffer);
 void v3dv_cmd_buffer_start_frame(struct v3dv_cmd_buffer *cmd_buffer,
                                  const struct v3dv_framebuffer *framebuffer);