v3dv: create a helper to start a new frame

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 1378cef..0f4c214 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -162,8 +162,8 @@
    vk_free(&cmd_buffer->pool->alloc, cmd_buffer);
 }
 
-static void
-emit_binning_flush(struct v3dv_job *job)
+void
+v3dv_job_emit_binning_flush(struct v3dv_job *job)
 {
    assert(job);
    v3dv_cl_ensure_space_with_branch(&job->bcl, cl_packet_length(FLUSH));
@@ -244,6 +244,83 @@
 }
 
 void
+v3dv_cmd_buffer_start_frame(struct v3dv_cmd_buffer *cmd_buffer,
+                            const struct v3dv_framebuffer *framebuffer)
+{
+   struct v3dv_job *job = cmd_buffer->state.job;
+   assert(job);
+
+   v3dv_cl_ensure_space_with_branch(&job->bcl, 256);
+
+   /* The PTB will request the tile alloc initial size per tile at start
+    * of tile binning.
+    */
+   uint32_t tile_alloc_size = 64 * framebuffer->layers *
+                              framebuffer->draw_tiles_x *
+                              framebuffer->draw_tiles_y;
+
+   /* The PTB allocates in aligned 4k chunks after the initial setup. */
+   tile_alloc_size = align(tile_alloc_size, 4096);
+
+   /* Include the first two chunk allocations that the PTB does so that
+    * we definitely clear the OOM condition before triggering one (the HW
+    * won't trigger OOM during the first allocations).
+    */
+   tile_alloc_size += 8192;
+
+   /* For performance, allocate some extra initial memory after the PTB's
+    * minimal allocations, so that we hopefully don't have to block the
+    * GPU on the kernel handling an OOM signal.
+    */
+   tile_alloc_size += 512 * 1024;
+
+   job->tile_alloc = v3dv_bo_alloc(cmd_buffer->device, tile_alloc_size);
+   v3dv_job_add_bo(job, job->tile_alloc);
+
+   const uint32_t tsda_per_tile_size = 256;
+   const uint32_t tile_state_size = framebuffer->layers *
+                                    framebuffer->draw_tiles_x *
+                                    framebuffer->draw_tiles_y *
+                                    tsda_per_tile_size;
+   job->tile_state = v3dv_bo_alloc(cmd_buffer->device, tile_state_size);
+   v3dv_job_add_bo(job, job->tile_state);
+
+   /* This must go before the binning mode configuration. It is
+    * required for layered framebuffers to work.
+    */
+   cl_emit(&job->bcl, NUMBER_OF_LAYERS, config) {
+      config.number_of_layers = framebuffer->layers;
+   }
+
+   cl_emit(&job->bcl, TILE_BINNING_MODE_CFG, config) {
+      config.width_in_pixels = framebuffer->width;
+      config.height_in_pixels = framebuffer->height;
+      config.number_of_render_targets = MAX2(framebuffer->attachment_count, 1);
+      config.multisample_mode_4x = false; /* FIXME */
+      config.maximum_bpp_of_all_render_targets = framebuffer->internal_bpp;
+   }
+
+   /* There's definitely nothing in the VCD cache we want. */
+   cl_emit(&job->bcl, FLUSH_VCD_CACHE, bin);
+
+   /* Disable any leftover OQ state from another job. */
+   cl_emit(&job->bcl, OCCLUSION_QUERY_COUNTER, counter);
+
+   /* "Binning mode lists must have a Start Tile Binning item (6) after
+    *  any prefix state data before the binning list proper starts."
+    */
+   cl_emit(&job->bcl, START_TILE_BINNING, bin);
+}
+
+static void
+cmd_buffer_end_render_pass_frame(struct v3dv_cmd_buffer *cmd_buffer)
+{
+   assert(cmd_buffer->state.job);
+   emit_rcl(cmd_buffer);
+   v3dv_job_emit_binning_flush(cmd_buffer->state.job);
+}
+
+void
 v3dv_cmd_buffer_finish_job(struct v3dv_cmd_buffer *cmd_buffer)
 {
    struct v3dv_job *job = cmd_buffer->state.job;
@@ -256,10 +333,8 @@
     * the RCL should have been emitted by the time we got here.
     */
    assert(v3dv_cl_offset(&job->rcl) != 0 || cmd_buffer->state.pass);
-   if (cmd_buffer->state.pass) {
-      emit_rcl(cmd_buffer);
-      emit_binning_flush(job);
-   }
+   if (cmd_buffer->state.pass)
+      cmd_buffer_end_render_pass_frame(cmd_buffer);
 
    list_addtail(&job->list_link, &cmd_buffer->submit_jobs);
    cmd_buffer->state.job = NULL;
@@ -1087,74 +1162,8 @@
    struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer);
 
    /* If we are starting a new job we need to setup binning. */
-   if (job->first_subpass == state->subpass_idx) {
-      const struct v3dv_framebuffer *framebuffer =
-         cmd_buffer->state.framebuffer;
-
-      v3dv_cl_ensure_space_with_branch(&job->bcl, 256);
-
-      /* The PTB will request the tile alloc initial size per tile at start
-       * of tile binning.
-       */
-      const uint32_t fb_layers = 1; /* FIXME */
-      uint32_t tile_alloc_size = 64 * MAX2(fb_layers, 1) *
-                                 framebuffer->draw_tiles_x *
-                                 framebuffer->draw_tiles_y;
-
-      /* The PTB allocates in aligned 4k chunks after the initial setup. */
-      tile_alloc_size = align(tile_alloc_size, 4096);
-
-      /* Include the first two chunk allocations that the PTB does so that
-       * we definitely clear the OOM condition before triggering one (the HW
-       * won't trigger OOM during the first allocations).
-       */
-      tile_alloc_size += 8192;
-
-      /* For performance, allocate some extra initial memory after the PTB's
-       * minimal allocations, so that we hopefully don't have to block the
-       * GPU on the kernel handling an OOM signal.
-       */
-      tile_alloc_size += 512 * 1024;
-
-      job->tile_alloc = v3dv_bo_alloc(cmd_buffer->device, tile_alloc_size);
-      v3dv_job_add_bo(job, job->tile_alloc);
-
-      const uint32_t tsda_per_tile_size = 256;
-      const uint32_t tile_state_size = MAX2(fb_layers, 1) *
-                                       framebuffer->draw_tiles_x *
-                                       framebuffer->draw_tiles_y *
-                                       tsda_per_tile_size;
-      job->tile_state = v3dv_bo_alloc(cmd_buffer->device, tile_state_size);
-      v3dv_job_add_bo(job, job->tile_state);
-
-      /* This must go before the binning mode configuration. It is
-       * required for layered framebuffers to work.
-       */
-      if (fb_layers > 0) {
-         cl_emit(&job->bcl, NUMBER_OF_LAYERS, config) {
-            config.number_of_layers = fb_layers;
-         }
-      }
-
-      cl_emit(&job->bcl, TILE_BINNING_MODE_CFG, config) {
-         config.width_in_pixels = framebuffer->width;
-         config.height_in_pixels = framebuffer->height;
-         config.number_of_render_targets = MAX2(framebuffer->attachment_count, 1);
-         config.multisample_mode_4x = false; /* FIXME */
-         config.maximum_bpp_of_all_render_targets = framebuffer->internal_bpp;
-      }
-
-      /* There's definitely nothing in the VCD cache we want. */
-      cl_emit(&job->bcl, FLUSH_VCD_CACHE, bin);
-
-      /* Disable any leftover OQ state from another job. */
-      cl_emit(&job->bcl, OCCLUSION_QUERY_COUNTER, counter);
-
-      /* "Binning mode lists must have a Start Tile Binning item (6) after
-       *  any prefix state data before the binning list proper starts."
-       */
-      cl_emit(&job->bcl, START_TILE_BINNING, bin);
-   }
+   if (job->first_subpass == state->subpass_idx)
+      v3dv_cmd_buffer_start_frame(cmd_buffer, cmd_buffer->state.framebuffer);
 
    /* If we don't have a scissor or viewport defined let's just use the render
     * area as clip_window, as that would be required for a clear in any
diff --git a/src/broadcom/vulkan/v3dv_meta_copy.c b/src/broadcom/vulkan/v3dv_meta_copy.c
index e2d3825..c3adab8 100644
--- a/src/broadcom/vulkan/v3dv_meta_copy.c
+++ b/src/broadcom/vulkan/v3dv_meta_copy.c
@@ -269,41 +269,6 @@
    cl_emit(rcl, END_OF_RENDERING, end);
 }
 
-static void
-emit_copy_image_to_buffer_bcl(struct v3dv_job *job,
-                              struct v3dv_framebuffer *framebuffer,
-                              const VkBufferImageCopy *region)
-{
-   v3dv_cl_ensure_space_with_branch(&job->bcl, 256);
-
-   cl_emit(&job->bcl, NUMBER_OF_LAYERS, config) {
-      config.number_of_layers = framebuffer->layers;
-   }
-
-   cl_emit(&job->bcl, TILE_BINNING_MODE_CFG, config) {
-      config.width_in_pixels = framebuffer->width;
-      config.height_in_pixels = framebuffer->height;
-      config.number_of_render_targets = 1;
-      config.multisample_mode_4x = false; /* FIXME */
-      config.maximum_bpp_of_all_render_targets = framebuffer->internal_bpp;
-   }
-
-   cl_emit(&job->bcl, FLUSH_VCD_CACHE, bin);
-
-   cl_emit(&job->bcl, OCCLUSION_QUERY_COUNTER, counter);
-
-   cl_emit(&job->bcl, START_TILE_BINNING, bin);
-
-   cl_emit(&job->bcl, CLIP_WINDOW, clip) {
-      clip.clip_window_left_pixel_coordinate = region->imageOffset.x;
-      clip.clip_window_bottom_pixel_coordinate = region->imageOffset.y;
-      clip.clip_window_width_in_pixels = region->imageExtent.width;
-      clip.clip_window_height_in_pixels = region->imageExtent.height;
-   }
-
-   cl_emit(&job->bcl, FLUSH, flush);
-}
-
 /* Sets framebuffer dimensions and computes tile size parameters based on the
  * maximum internal bpp provided.
  */
@@ -361,25 +326,9 @@
       setup_framebuffer_params(&framebuffer, image, num_layers, internal_bpp);
 
       struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer);
+      v3dv_cmd_buffer_start_frame(cmd_buffer, &framebuffer);
 
-      uint32_t tile_alloc_size = 64 * num_layers *
-                                 framebuffer.draw_tiles_x *
-                                 framebuffer.draw_tiles_y;
-      tile_alloc_size = align(tile_alloc_size, 4096);
-      tile_alloc_size += 8192;
-      tile_alloc_size += 512 * 1024;
-      job->tile_alloc = v3dv_bo_alloc(cmd_buffer->device, tile_alloc_size);
-      v3dv_job_add_bo(job, job->tile_alloc);
-
-      const uint32_t tsda_per_tile_size = 256;
-      const uint32_t tile_state_size = num_layers *
-                                       framebuffer.draw_tiles_x *
-                                       framebuffer.draw_tiles_y *
-                                       tsda_per_tile_size;
-      job->tile_state = v3dv_bo_alloc(cmd_buffer->device, tile_state_size);
-      v3dv_job_add_bo(job, job->tile_state);
-
-      emit_copy_image_to_buffer_bcl(job, &framebuffer, region);
+      v3dv_job_emit_binning_flush(job);
       emit_copy_image_to_buffer_rcl(job, buffer, image,
                                     &framebuffer, internal_type, region);
 
diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h
index 9fce92b..32400b9 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -469,6 +469,7 @@
 };
 
 void v3dv_job_add_bo(struct v3dv_job *job, struct v3dv_bo *bo);
+void v3dv_job_emit_binning_flush(struct v3dv_job *job);
 
 struct v3dv_cmd_buffer_state {
    const struct v3dv_render_pass *pass;
@@ -510,6 +511,8 @@
 
 struct v3dv_job *v3dv_cmd_buffer_start_job(struct v3dv_cmd_buffer *cmd_buffer);
 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);
 
 struct v3dv_shader_module {
    unsigned char sha1[20];