v3dv: more frame tiling refactors
authorIago Toral Quiroga <itoral@igalia.com>
Tue, 3 Mar 2020 10:57:59 +0000 (11:57 +0100)
committerMarge Bot <eric+marge@anholt.net>
Tue, 13 Oct 2020 21:21:28 +0000 (21:21 +0000)
This puts all the information required to setup frame tiling into
v3dv_frame_tiling so we no longer need a framebuffer to start a
frame. This makes the code simpler, since frame tiling calculations
happen automatically when we start a new frame and simplifies
the implementation of copy and clear operations that used to
requiere that we setup a fake framebuffer with no actual attachments,
which was a bit of a kludge.

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

src/broadcom/vulkan/v3dv_cmd_buffer.c
src/broadcom/vulkan/v3dv_device.c
src/broadcom/vulkan/v3dv_meta_clear.c
src/broadcom/vulkan/v3dv_meta_copy.c
src/broadcom/vulkan/v3dv_private.h

index d6b667f..28b8a08 100644 (file)
@@ -293,24 +293,99 @@ cmd_buffer_can_merge_subpass(struct v3dv_cmd_buffer *cmd_buffer)
    return true;
 }
 
+/**
+ * Computes and sets the job frame tiling information required to setup frame
+ * binning and rendering.
+ */
+static struct v3dv_frame_tiling *
+job_compute_frame_tiling(struct v3dv_job *job,
+                         uint32_t width,
+                         uint32_t height,
+                         uint32_t layers,
+                         uint32_t render_target_count,
+                         uint8_t max_internal_bpp)
+{
+   static const uint8_t tile_sizes[] = {
+      64, 64,
+      64, 32,
+      32, 32,
+      32, 16,
+      16, 16,
+   };
+
+   assert(job);
+   struct v3dv_frame_tiling *tiling = &job->frame_tiling;
+
+   tiling->width = width;
+   tiling->height = height;
+   tiling->layers = layers;
+   tiling->render_target_count = render_target_count;
+
+   uint32_t tile_size_index = 0;
+
+   /* FIXME: MSAA */
+
+   if (render_target_count > 2)
+      tile_size_index += 2;
+   else if (render_target_count > 1)
+      tile_size_index += 1;
+
+   tiling->internal_bpp = max_internal_bpp;
+   tile_size_index += tiling->internal_bpp;
+   assert(tile_size_index < ARRAY_SIZE(tile_sizes));
+
+   tiling->tile_width = tile_sizes[tile_size_index * 2];
+   tiling->tile_height = tile_sizes[tile_size_index * 2 + 1];
+
+   tiling->draw_tiles_x = DIV_ROUND_UP(width, tiling->tile_width);
+   tiling->draw_tiles_y = DIV_ROUND_UP(height, tiling->tile_height);
+
+   /* Size up our supertiles until we get under the limit */
+   const uint32_t max_supertiles = 256;
+   tiling->supertile_width = 1;
+   tiling->supertile_height = 1;
+   for (;;) {
+      tiling->frame_width_in_supertiles =
+         DIV_ROUND_UP(tiling->draw_tiles_x, tiling->supertile_width);
+      tiling->frame_height_in_supertiles =
+         DIV_ROUND_UP(tiling->draw_tiles_y, tiling->supertile_height);
+      const uint32_t num_supertiles = tiling->frame_width_in_supertiles *
+                                      tiling->frame_height_in_supertiles;
+      if (num_supertiles < max_supertiles)
+         break;
+
+      if (tiling->supertile_width < tiling->supertile_height)
+         tiling->supertile_width++;
+      else
+         tiling->supertile_height++;
+   }
+
+   return tiling;
+}
+
 void
 v3dv_cmd_buffer_start_frame(struct v3dv_cmd_buffer *cmd_buffer,
-                            const struct v3dv_framebuffer *framebuffer,
-                            const struct v3dv_frame_tiling *tiling,
-                            int32_t num_render_targets)
+                            uint32_t width,
+                            uint32_t height,
+                            uint32_t layers,
+                            uint32_t render_target_count,
+                            uint8_t max_internal_bpp)
 {
    struct v3dv_job *job = cmd_buffer->state.job;
    assert(job);
 
-   /* Copy the frame tiling spec into the job */
-   memcpy(&job->frame_tiling, tiling, sizeof(struct v3dv_frame_tiling));
+   /* Start by computing frame tiling spec for this job */
+   const struct v3dv_frame_tiling *tiling =
+      job_compute_frame_tiling(job,
+                               width, height, layers,
+                               render_target_count, max_internal_bpp);
 
    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 *
+   uint32_t tile_alloc_size = 64 * tiling->layers *
                               tiling->draw_tiles_x *
                               tiling->draw_tiles_y;
 
@@ -334,7 +409,7 @@ v3dv_cmd_buffer_start_frame(struct v3dv_cmd_buffer *cmd_buffer,
    v3dv_job_add_bo(job, job->tile_alloc);
 
    const uint32_t tsda_per_tile_size = 256;
-   const uint32_t tile_state_size = framebuffer->layers *
+   const uint32_t tile_state_size = tiling->layers *
                                     tiling->draw_tiles_x *
                                     tiling->draw_tiles_y *
                                     tsda_per_tile_size;
@@ -345,16 +420,13 @@ v3dv_cmd_buffer_start_frame(struct v3dv_cmd_buffer *cmd_buffer,
     * required for layered framebuffers to work.
     */
    cl_emit(&job->bcl, NUMBER_OF_LAYERS, config) {
-      config.number_of_layers = framebuffer->layers;
+      config.number_of_layers = layers;
    }
 
-   if (num_render_targets == -1)
-      num_render_targets = framebuffer->color_attachment_count;
-
    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(num_render_targets, 1);
+      config.width_in_pixels = tiling->width;
+      config.height_in_pixels = tiling->height;
+      config.number_of_render_targets = MAX2(tiling->render_target_count, 1);
       config.multisample_mode_4x = false; /* FIXME */
       config.maximum_bpp_of_all_render_targets = tiling->internal_bpp;
    }
@@ -1421,12 +1493,12 @@ subpass_start(struct v3dv_cmd_buffer *cmd_buffer, uint32_t subpass_idx)
       const uint8_t internal_bpp =
          v3dv_framebuffer_compute_internal_bpp(framebuffer, subpass);
 
-      struct v3dv_frame_tiling frame_tiling;
-      v3dv_framebuffer_compute_tiling_params(framebuffer, subpass, internal_bpp,
-                                             &frame_tiling);
-
-      v3dv_cmd_buffer_start_frame(cmd_buffer, framebuffer, &frame_tiling,
-                                  subpass->color_count);
+      v3dv_cmd_buffer_start_frame(cmd_buffer,
+                                  framebuffer->width,
+                                  framebuffer->height,
+                                  framebuffer->layers,
+                                  subpass->color_count,
+                                  internal_bpp);
    }
 
    /* If we don't have a scissor or viewport defined let's just use the render
index e5417b8..5cbbb9b 100644 (file)
@@ -1659,6 +1659,11 @@ v3dv_DestroyBuffer(VkDevice _device,
    vk_free2(&device->alloc, pAllocator, buffer);
 }
 
+/**
+ * This computes the maximum bpp used by any of the render targets used by
+ * a particular subpass. If we don't have a subpass (when we are not inside a
+ * render pass), then we assume that all framebuffer attachments are used.
+ */
 uint8_t
 v3dv_framebuffer_compute_internal_bpp(const struct v3dv_framebuffer *framebuffer,
                                       const struct v3dv_subpass *subpass)
@@ -1682,9 +1687,6 @@ v3dv_framebuffer_compute_internal_bpp(const struct v3dv_framebuffer *framebuffer
       return max_bpp;
    }
 
-   /* If we are not in a render pass then we assume that all framebuffer
-    * attachments are used.
-    */
    assert(framebuffer->attachment_count <= 4);
    for (uint32_t i = 0; i < framebuffer->attachment_count; i++) {
       const struct v3dv_image_view *att = framebuffer->attachments[i];
@@ -1697,65 +1699,6 @@ v3dv_framebuffer_compute_internal_bpp(const struct v3dv_framebuffer *framebuffer
    return max_bpp;
 }
 
-void
-v3dv_framebuffer_compute_tiling_params(const struct v3dv_framebuffer *framebuffer,
-                                       const struct v3dv_subpass *subpass,
-                                       uint8_t internal_bpp,
-                                       struct v3dv_frame_tiling *tiling)
-{
-   static const uint8_t tile_sizes[] = {
-      64, 64,
-      64, 32,
-      32, 32,
-      32, 16,
-      16, 16,
-   };
-
-   uint32_t tile_size_index = 0;
-
-   /* FIXME: MSAA */
-
-   const uint32_t color_attachment_count =
-      subpass ? subpass->color_count : framebuffer->color_attachment_count;
-
-   if (color_attachment_count > 2)
-      tile_size_index += 2;
-   else if (color_attachment_count > 1)
-      tile_size_index += 1;
-
-   tiling->internal_bpp = internal_bpp;
-   tile_size_index += tiling->internal_bpp;
-   assert(tile_size_index < ARRAY_SIZE(tile_sizes));
-
-   tiling->tile_width = tile_sizes[tile_size_index * 2];
-   tiling->tile_height = tile_sizes[tile_size_index * 2 + 1];
-
-   tiling->draw_tiles_x =
-      DIV_ROUND_UP(framebuffer->width, tiling->tile_width);
-   tiling->draw_tiles_y =
-      DIV_ROUND_UP(framebuffer->height, tiling->tile_height);
-
-   /* Size up our supertiles until we get under the limit */
-   const uint32_t max_supertiles = 256;
-   tiling->supertile_width = 1;
-   tiling->supertile_height = 1;
-   for (;;) {
-      tiling->frame_width_in_supertiles =
-         DIV_ROUND_UP(tiling->draw_tiles_x, tiling->supertile_width);
-      tiling->frame_height_in_supertiles =
-         DIV_ROUND_UP(tiling->draw_tiles_y, tiling->supertile_height);
-      const uint32_t num_supertiles = tiling->frame_width_in_supertiles *
-                                      tiling->frame_height_in_supertiles;
-      if (num_supertiles < max_supertiles)
-         break;
-
-      if (tiling->supertile_width < tiling->supertile_height)
-         tiling->supertile_width++;
-      else
-         tiling->supertile_height++;
-   }
-}
-
 VkResult
 v3dv_CreateFramebuffer(VkDevice _device,
                        const VkFramebufferCreateInfo *pCreateInfo,
index 6b13f2e..9f736c8 100644 (file)
@@ -262,12 +262,12 @@ emit_tlb_clear_job(struct v3dv_cmd_buffer *cmd_buffer,
    const uint8_t internal_bpp =
       v3dv_framebuffer_compute_internal_bpp(framebuffer, subpass);
 
-   struct v3dv_frame_tiling frame_tiling;
-   v3dv_framebuffer_compute_tiling_params(framebuffer, subpass, internal_bpp,
-                                          &frame_tiling);
-
-   v3dv_cmd_buffer_start_frame(cmd_buffer, framebuffer, &frame_tiling,
-                               color_attachment_count);
+   v3dv_cmd_buffer_start_frame(cmd_buffer,
+                               framebuffer->width,
+                               framebuffer->height,
+                               framebuffer->layers,
+                               color_attachment_count,
+                               internal_bpp);
 
    struct v3dv_cl *rcl = &job->rcl;
    v3dv_cl_ensure_space_with_branch(rcl, 200 +
@@ -399,13 +399,13 @@ emit_tlb_clear(struct v3dv_cmd_buffer *cmd_buffer,
                uint32_t base_layer,
                uint32_t layer_count)
 {
-   const struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;
-   const struct v3dv_framebuffer *framebuffer = state->framebuffer;
-
    struct v3dv_job *job = cmd_buffer->state.job;
    assert(job);
 
-   /* Save a copy of the current subpass tiling spec */
+   /* Save a copy of the current subpass tiling spec, since we are about to
+    * split the job for the clear and we will need to then resume it with the
+    * same specs.
+    */
    struct v3dv_frame_tiling subpass_tiling;
    memcpy(&subpass_tiling, &job->frame_tiling, sizeof(subpass_tiling));
 
@@ -428,10 +428,14 @@ emit_tlb_clear(struct v3dv_cmd_buffer *cmd_buffer,
     * after the clear.
     */
    job = v3dv_cmd_buffer_start_job(cmd_buffer, false);
-   uint32_t subpass_color_count =
-      state->pass->subpasses[state->subpass_idx].color_count;
-   v3dv_cmd_buffer_start_frame(cmd_buffer, framebuffer, &subpass_tiling,
-                               subpass_color_count);
+
+   v3dv_cmd_buffer_start_frame(cmd_buffer,
+                               subpass_tiling.width,
+                               subpass_tiling.height,
+                               subpass_tiling.layers,
+                               subpass_tiling.render_target_count,
+                               subpass_tiling.internal_bpp);
+
    job->is_subpass_continue = true;
 }
 
index 244ed53..10753ad 100644 (file)
 #include "broadcom/cle/v3dx_pack.h"
 #include "vk_format_info.h"
 
-/* Most "copy" operations in this file are implemented using the tile buffer
- * to fill and/or copy buffers and images. To do that, we need to have some
- * representation of a framebuffer that describes the layout of the render
- * target and the tiling information. That information is typically represented
- * in a framebuffer object but for most operations in this file we don't have
- * one provided by the user, so instead we need to create one that matches
- * the semantics of the copy operation we want to implement. A "real"
- * framebuffer description includes references to image views (v3dv_image_view)
- * and their underlying images (v3dv_image) for each attachment though,
- * but here, we usually work with buffers instead of images, or we have images
- * but we don't have image views, so instead of trying to use a real
- * framebuffer we use a "fake" one, where we don't include attachment info
- * and we simply store the internal type of the single render target we are
- * copying to or filling with data.
+/**
+ * Copy operations implemented in this file don't operate on a framebuffer
+ * object provided by the user, however, since most use the TLB for this,
+ * we still need to have some representation of the framebuffer. For the most
+ * part, the job's frame tiling information is enough for this, however we
+ * still need additional information such us the internal type of our single
+ * render target, so we use this auxiliary struct to pass that information
+ * around.
  */
-struct fake_framebuffer {
-   struct v3dv_framebuffer fb;
-   struct v3dv_frame_tiling tiling;
+struct framebuffer_data {
+   /* The internal type of the single render target */
    uint32_t internal_type;
+
+   /* Supertile coverage */
    uint32_t min_x_supertile;
    uint32_t min_y_supertile;
    uint32_t max_x_supertile;
    uint32_t max_y_supertile;
 };
 
-/* Sets framebuffer dimensions and computes tile size parameters based on the
- * maximum internal bpp provided.
- */
 static void
-setup_framebuffer_params(struct fake_framebuffer *fb,
-                         uint32_t width,
-                         uint32_t height,
-                         uint32_t layer_count,
-                         uint32_t internal_bpp,
-                         uint32_t internal_type)
+setup_framebuffer_data(struct framebuffer_data *fb,
+                       uint32_t internal_type,
+                       const struct v3dv_frame_tiling *tiling)
 {
-   fb->fb.width  = width;
-   fb->fb.height = height;
-   fb->fb.layers = layer_count;
-
-   /* We are only interested in the framebufer description required to compute
-    * the tiling setup parameters below, so we don't need real attachments,
-    * only the framebuffer size, the internal bpp and the number of attachments.
-    */
-   fb->fb.attachment_count = 1;
-   fb->fb.color_attachment_count = 1;
-
-   /* For simplicity, we store the internal type of the single render target
-    * that functions in this file need in the fake framebuffer objects so
-    * we don't have to pass it around everywhere.
-    */
    fb->internal_type = internal_type;
 
-   fb->tiling.internal_bpp = MAX2(RENDER_TARGET_MAXIMUM_32BPP, internal_bpp);
-   v3dv_framebuffer_compute_tiling_params(&fb->fb, NULL,
-                                          fb->tiling.internal_bpp, &fb->tiling);
-
+   /* Supertile coverage always starts at 0,0  */
    uint32_t supertile_w_in_pixels =
-      fb->tiling.tile_width * fb->tiling.supertile_width;
+      tiling->tile_width * tiling->supertile_width;
    uint32_t supertile_h_in_pixels =
-      fb->tiling.tile_height * fb->tiling.supertile_height;
+      tiling->tile_height * tiling->supertile_height;
+
    fb->min_x_supertile = 0;
    fb->min_y_supertile = 0;
-   fb->max_x_supertile = (fb->fb.width - 1) / supertile_w_in_pixels;
-   fb->max_y_supertile = (fb->fb.height - 1) / supertile_h_in_pixels;
+   fb->max_x_supertile = (tiling->width - 1) / supertile_w_in_pixels;
+   fb->max_y_supertile = (tiling->height - 1) / supertile_h_in_pixels;
+
 }
 
 /* This chooses a tile buffer format that is appropriate for the copy operation.
@@ -208,23 +181,24 @@ get_internal_type_bpp_for_image_aspects(struct v3dv_image *image,
 
 static struct v3dv_cl *
 emit_rcl_prologue(struct v3dv_job *job,
-                  struct fake_framebuffer *framebuffer,
+                  struct framebuffer_data *framebuffer,
                   const union v3dv_clear_value *clear_value,
                   struct v3dv_image *image,
                   VkImageAspectFlags aspects,
                   uint32_t layer,
                   uint32_t level)
 {
+   const struct v3dv_frame_tiling *tiling = &job->frame_tiling;
+
    struct v3dv_cl *rcl = &job->rcl;
    v3dv_cl_ensure_space_with_branch(rcl, 200 +
-                                    framebuffer->fb.layers * 256 *
+                                    tiling->layers * 256 *
                                     cl_packet_length(SUPERTILE_COORDINATES));
 
-   const struct v3dv_frame_tiling *tiling = &framebuffer->tiling;
    cl_emit(rcl, TILE_RENDERING_MODE_CFG_COMMON, config) {
       config.early_z_disable = true;
-      config.image_width_pixels = framebuffer->fb.width;
-      config.image_height_pixels = framebuffer->fb.height;
+      config.image_width_pixels = tiling->width;
+      config.image_height_pixels = tiling->height;
       config.number_of_render_targets = 1;
       config.multisample_mode_4x = false;
       config.maximum_bpp_of_all_render_targets = tiling->internal_bpp;
@@ -240,7 +214,7 @@ emit_rcl_prologue(struct v3dv_job *job,
             int uif_block_height = v3d_utile_height(image->cpp) * 2;
 
             uint32_t implicit_padded_height =
-               align(framebuffer->fb.height, uif_block_height) / uif_block_height;
+               align(tiling->height, uif_block_height) / uif_block_height;
 
             if (slice->padded_height_of_output_image_in_uif_blocks -
                 implicit_padded_height >= 15) {
@@ -297,31 +271,31 @@ emit_rcl_prologue(struct v3dv_job *job,
 
 static void
 emit_frame_setup(struct v3dv_job *job,
-                 struct fake_framebuffer *framebuffer,
+                 struct framebuffer_data *framebuffer,
                  uint32_t layer,
                  const union v3dv_clear_value *clear_value)
 {
+   const struct v3dv_frame_tiling *tiling = &job->frame_tiling;
    struct v3dv_cl *rcl = &job->rcl;
 
    const uint32_t tile_alloc_offset =
-      64 * layer * framebuffer->tiling.draw_tiles_x *
-      framebuffer->tiling.draw_tiles_y;
+      64 * layer * tiling->draw_tiles_x * tiling->draw_tiles_y;
    cl_emit(rcl, MULTICORE_RENDERING_TILE_LIST_SET_BASE, list) {
       list.address = v3dv_cl_address(job->tile_alloc, tile_alloc_offset);
    }
 
    cl_emit(rcl, MULTICORE_RENDERING_SUPERTILE_CFG, config) {
       config.number_of_bin_tile_lists = 1;
-      config.total_frame_width_in_tiles = framebuffer->tiling.draw_tiles_x;
-      config.total_frame_height_in_tiles = framebuffer->tiling.draw_tiles_y;
+      config.total_frame_width_in_tiles = tiling->draw_tiles_x;
+      config.total_frame_height_in_tiles = tiling->draw_tiles_y;
 
-      config.supertile_width_in_tiles = framebuffer->tiling.supertile_width;
-      config.supertile_height_in_tiles = framebuffer->tiling.supertile_height;
+      config.supertile_width_in_tiles = tiling->supertile_width;
+      config.supertile_height_in_tiles = tiling->supertile_height;
 
       config.total_frame_width_in_supertiles =
-         framebuffer->tiling.frame_width_in_supertiles;
+         tiling->frame_width_in_supertiles;
       config.total_frame_height_in_supertiles =
-         framebuffer->tiling.frame_height_in_supertiles;
+         tiling->frame_height_in_supertiles;
    }
 
    /* Implement GFXH-1742 workaround. Also, if we are clearing we have to do
@@ -347,7 +321,7 @@ emit_frame_setup(struct v3dv_job *job,
 
 static void
 emit_supertile_coordinates(struct v3dv_job *job,
-                           struct fake_framebuffer *framebuffer)
+                           struct framebuffer_data *framebuffer)
 {
    struct v3dv_cl *rcl = &job->rcl;
 
@@ -612,7 +586,7 @@ static void
 emit_copy_layer_to_buffer(struct v3dv_job *job,
                           struct v3dv_buffer *buffer,
                           struct v3dv_image *image,
-                          struct fake_framebuffer *framebuffer,
+                          struct framebuffer_data *framebuffer,
                           uint32_t layer,
                           const VkBufferImageCopy *region)
 {
@@ -625,13 +599,13 @@ static void
 emit_copy_image_to_buffer_rcl(struct v3dv_job *job,
                               struct v3dv_buffer *buffer,
                               struct v3dv_image *image,
-                              struct fake_framebuffer *framebuffer,
+                              struct framebuffer_data *framebuffer,
                               const VkBufferImageCopy *region)
 {
    struct v3dv_cl *rcl = emit_rcl_prologue(job, framebuffer, NULL, NULL,
                                            region->imageSubresource.aspectMask,
                                            0, 0);
-   for (int layer = 0; layer < framebuffer->fb.layers; layer++)
+   for (int layer = 0; layer < job->frame_tiling.layers; layer++)
       emit_copy_layer_to_buffer(job, buffer, image, framebuffer, layer, region);
    cl_emit(rcl, END_OF_RENDERING, end);
 }
@@ -664,31 +638,15 @@ copy_image_to_buffer_tlb(struct v3dv_cmd_buffer *cmd_buffer,
    uint32_t num_layers = region->imageSubresource.layerCount;
    assert(num_layers > 0);
 
-   struct fake_framebuffer framebuffer;
-   setup_framebuffer_params(&framebuffer,
-                            region->imageExtent.width,
-                            region->imageExtent.height,
-                            num_layers, internal_bpp, internal_type);
-
-   /* Limit supertile coverage to the requested region  */
-   uint32_t supertile_w_in_pixels =
-      framebuffer.tiling.tile_width * framebuffer.tiling.supertile_width;
-   uint32_t supertile_h_in_pixels =
-      framebuffer.tiling.tile_height * framebuffer.tiling.supertile_height;
-   const uint32_t max_render_x =
-      region->imageOffset.x + region->imageExtent.width - 1;
-   const uint32_t max_render_y =
-      region->imageOffset.y + region->imageExtent.height - 1;
-
-   assert(region->imageOffset.x == 0 && region->imageOffset.y == 0);
-   framebuffer.min_x_supertile = 0;
-   framebuffer.min_y_supertile = 0;
-   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, -1);
+
    v3dv_cmd_buffer_start_frame(cmd_buffer,
-                               &framebuffer.fb, &framebuffer.tiling, 1);
+                               region->imageExtent.width,
+                               region->imageExtent.height,
+                               num_layers, 1, internal_bpp);
+
+   struct framebuffer_data framebuffer;
+   setup_framebuffer_data(&framebuffer, internal_type, &job->frame_tiling);
 
    v3dv_job_emit_binning_flush(job);
    emit_copy_image_to_buffer_rcl(job, buffer, image, &framebuffer, region);
@@ -768,7 +726,7 @@ static void
 emit_copy_image_layer(struct v3dv_job *job,
                       struct v3dv_image *dst,
                       struct v3dv_image *src,
-                      struct fake_framebuffer *framebuffer,
+                      struct framebuffer_data *framebuffer,
                       uint32_t layer,
                       const VkImageCopy *region)
 {
@@ -781,13 +739,13 @@ static void
 emit_copy_image_rcl(struct v3dv_job *job,
                     struct v3dv_image *dst,
                     struct v3dv_image *src,
-                    struct fake_framebuffer *framebuffer,
+                    struct framebuffer_data *framebuffer,
                     const VkImageCopy *region)
 {
    struct v3dv_cl *rcl = emit_rcl_prologue(job, framebuffer, NULL, NULL,
                                            region->dstSubresource.aspectMask,
                                            0, 0);
-   for (int layer = 0; layer < framebuffer->fb.layers; layer++)
+   for (int layer = 0; layer < job->frame_tiling.layers; layer++)
       emit_copy_image_layer(job, dst, src, framebuffer, layer, region);
    cl_emit(rcl, END_OF_RENDERING, end);
 }
@@ -822,28 +780,15 @@ copy_image_tlb(struct v3dv_cmd_buffer *cmd_buffer,
    uint32_t num_layers = region->dstSubresource.layerCount;
    assert(num_layers > 0);
 
-   struct fake_framebuffer framebuffer;
-   setup_framebuffer_params(&framebuffer,
-                            region->extent.width, region->extent.height,
-                            num_layers, internal_bpp, internal_type);
-
-   /* Limit supertile coverage to the requested region  */
-   uint32_t supertile_w_in_pixels =
-      framebuffer.tiling.tile_width * framebuffer.tiling.supertile_width;
-   uint32_t supertile_h_in_pixels =
-      framebuffer.tiling.tile_height * framebuffer.tiling.supertile_height;
-   const uint32_t max_render_x = region->extent.width - 1;
-   const uint32_t max_render_y = region->extent.height - 1;
-
-   assert(region->dstOffset.x == 0 && region->dstOffset.y == 0);
-   framebuffer.min_x_supertile = 0;
-   framebuffer.min_y_supertile = 0;
-   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, -1);
+
    v3dv_cmd_buffer_start_frame(cmd_buffer,
-                               &framebuffer.fb, &framebuffer.tiling, 1);
+                               region->extent.width,
+                               region->extent.height,
+                               num_layers, 1, internal_bpp);
+
+   struct framebuffer_data framebuffer;
+   setup_framebuffer_data(&framebuffer, internal_type, &job->frame_tiling);
 
    v3dv_job_emit_binning_flush(job);
    emit_copy_image_rcl(job, dst, src, &framebuffer, region);
@@ -906,7 +851,7 @@ emit_clear_image_per_tile_list(struct v3dv_job *job,
 static void
 emit_clear_image(struct v3dv_job *job,
                  struct v3dv_image *image,
-                 struct fake_framebuffer *framebuffer,
+                 struct framebuffer_data *framebuffer,
                  VkImageAspectFlags aspects,
                  uint32_t layer,
                  uint32_t level)
@@ -918,7 +863,7 @@ emit_clear_image(struct v3dv_job *job,
 static void
 emit_clear_image_rcl(struct v3dv_job *job,
                      struct v3dv_image *image,
-                     struct fake_framebuffer *framebuffer,
+                     struct framebuffer_data *framebuffer,
                      const union v3dv_clear_value *clear_value,
                      VkImageAspectFlags aspects,
                      uint32_t layer,
@@ -970,13 +915,14 @@ clear_image_tlb(struct v3dv_cmd_buffer *cmd_buffer,
          uint32_t width = u_minify(image->extent.width, level);
          uint32_t height = u_minify(image->extent.height, level);
 
-         struct fake_framebuffer framebuffer;
-         setup_framebuffer_params(&framebuffer, width, height, 1,
-                                  internal_bpp, internal_type);
-
          struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, -1);
-   v3dv_cmd_buffer_start_frame(cmd_buffer,
-                               &framebuffer.fb, &framebuffer.tiling, 1);
+
+         v3dv_cmd_buffer_start_frame(cmd_buffer, width, height, 1,
+                                     1, internal_bpp);
+
+         struct framebuffer_data framebuffer;
+         setup_framebuffer_data(&framebuffer, internal_type, &job->frame_tiling);
+
          v3dv_job_emit_binning_flush(job);
 
          /* If this triggers it is an application bug: the spec requires
@@ -1073,10 +1019,10 @@ emit_copy_buffer(struct v3dv_job *job,
                  struct v3dv_bo *src,
                  uint32_t dst_offset,
                  uint32_t src_offset,
-                 struct fake_framebuffer *framebuffer,
+                 struct framebuffer_data *framebuffer,
                  uint32_t format)
 {
-   const uint32_t stride = framebuffer->fb.width * 4;
+   const uint32_t stride = job->frame_tiling.width * 4;
    emit_copy_buffer_per_tile_list(job, dst, src,
                                   dst_offset, src_offset,
                                   stride, format);
@@ -1089,7 +1035,7 @@ emit_copy_buffer_rcl(struct v3dv_job *job,
                      struct v3dv_bo *src,
                      uint32_t dst_offset,
                      uint32_t src_offset,
-                     struct fake_framebuffer *framebuffer,
+                     struct framebuffer_data *framebuffer,
                      uint32_t format)
 {
    struct v3dv_cl *rcl = emit_rcl_prologue(job, framebuffer, NULL, NULL,
@@ -1105,11 +1051,12 @@ emit_copy_buffer_rcl(struct v3dv_job *job,
  * the job and call this function multiple times.
  */
 static void
-setup_framebuffer_for_pixel_count(struct fake_framebuffer *framebuffer,
-                                  uint32_t num_pixels,
-                                  uint32_t internal_bpp,
-                                  uint32_t internal_type)
+framebuffer_size_for_pixel_count(uint32_t num_pixels,
+                                 uint32_t *width,
+                                 uint32_t *height)
 {
+   assert(num_pixels > 0);
+
    const uint32_t max_dim_pixels = 4096;
    const uint32_t max_pixels = max_dim_pixels * max_dim_pixels;
 
@@ -1127,15 +1074,10 @@ setup_framebuffer_for_pixel_count(struct fake_framebuffer *framebuffer,
    }
    assert(w <= max_dim_pixels && h <= max_dim_pixels);
    assert(w * h <= num_pixels);
+   assert(w > 0 && h > 0);
 
-   /* Skip tiling calculations if the framebuffer setup has not changed */
-   if (w != framebuffer->fb.width ||
-       h != framebuffer->fb.height ||
-       internal_bpp != framebuffer->tiling.internal_bpp ||
-       internal_type != framebuffer->internal_type) {
-      setup_framebuffer_params(framebuffer, w, h, 1,
-                               internal_bpp, internal_type);
-   }
+   *width = w;
+   *height = h;
 }
 
 static struct v3dv_job *
@@ -1175,14 +1117,17 @@ copy_buffer(struct v3dv_cmd_buffer *cmd_buffer,
    struct v3dv_job *job;
    uint32_t src_offset = region->srcOffset;
    uint32_t dst_offset = region->dstOffset;
-   struct fake_framebuffer framebuffer = { .fb.width = 0 };
    while (num_items > 0) {
-      setup_framebuffer_for_pixel_count(&framebuffer, num_items,
-                                        internal_bpp, internal_type);
-
       job = v3dv_cmd_buffer_start_job(cmd_buffer, -1);
-   v3dv_cmd_buffer_start_frame(cmd_buffer,
-                               &framebuffer.fb, &framebuffer.tiling, 1);
+
+      uint32_t width, height;
+      framebuffer_size_for_pixel_count(num_items, &width, &height);
+
+      v3dv_cmd_buffer_start_frame(cmd_buffer, width, height, 1,
+                                  1, internal_bpp);
+
+      struct framebuffer_data framebuffer;
+      setup_framebuffer_data(&framebuffer, internal_type, &job->frame_tiling);
 
       v3dv_job_emit_binning_flush(job);
 
@@ -1191,7 +1136,7 @@ copy_buffer(struct v3dv_cmd_buffer *cmd_buffer,
 
       v3dv_cmd_buffer_finish_job(cmd_buffer);
 
-      const uint32_t items_copied = framebuffer.fb.width * framebuffer.fb.height;
+      const uint32_t items_copied = width * height;
       const uint32_t bytes_copied = items_copied * item_size;
       num_items -= items_copied;
       src_offset += bytes_copied;
@@ -1293,9 +1238,9 @@ static void
 emit_fill_buffer(struct v3dv_job *job,
                  struct v3dv_bo *bo,
                  uint32_t offset,
-                 struct fake_framebuffer *framebuffer)
+                 struct framebuffer_data *framebuffer)
 {
-   const uint32_t stride = framebuffer->fb.width * 4;
+   const uint32_t stride = job->frame_tiling.width * 4;
    emit_fill_buffer_per_tile_list(job, bo, offset, stride);
    emit_supertile_coordinates(job, framebuffer);
 }
@@ -1304,7 +1249,7 @@ static void
 emit_fill_buffer_rcl(struct v3dv_job *job,
                      struct v3dv_bo *bo,
                      uint32_t offset,
-                     struct fake_framebuffer *framebuffer,
+                     struct framebuffer_data *framebuffer,
                      uint32_t data)
 {
    const union v3dv_clear_value clear_value = {
@@ -1332,14 +1277,16 @@ fill_buffer(struct v3dv_cmd_buffer *cmd_buffer,
    const uint32_t internal_type = V3D_INTERNAL_TYPE_8UI;
    uint32_t num_items = size / 4;
 
-   struct fake_framebuffer framebuffer = { .fb.width = 0 };
    while (num_items > 0) {
-      setup_framebuffer_for_pixel_count(&framebuffer, num_items,
-                                        internal_bpp, internal_type);
-
       struct v3dv_job *job = v3dv_cmd_buffer_start_job(cmd_buffer, -1);
-   v3dv_cmd_buffer_start_frame(cmd_buffer,
-                               &framebuffer.fb, &framebuffer.tiling, 1);
+
+      uint32_t width, height;
+      framebuffer_size_for_pixel_count(num_items, &width, &height);
+
+      v3dv_cmd_buffer_start_frame(cmd_buffer, width, height, 1, 1, internal_bpp);
+
+      struct framebuffer_data framebuffer;
+      setup_framebuffer_data(&framebuffer, internal_type, &job->frame_tiling);
 
       v3dv_job_emit_binning_flush(job);
 
@@ -1347,7 +1294,7 @@ fill_buffer(struct v3dv_cmd_buffer *cmd_buffer,
 
       v3dv_cmd_buffer_finish_job(cmd_buffer);
 
-      const uint32_t items_copied = framebuffer.fb.width * framebuffer.fb.height;
+      const uint32_t items_copied = width * height;
       const uint32_t bytes_copied = items_copied * 4;
       num_items -= items_copied;
       offset += bytes_copied;
@@ -1480,7 +1427,7 @@ static void
 emit_copy_buffer_to_layer(struct v3dv_job *job,
                           struct v3dv_image *image,
                           struct v3dv_buffer *buffer,
-                          struct fake_framebuffer *framebuffer,
+                          struct framebuffer_data *framebuffer,
                           uint32_t layer,
                           const VkBufferImageCopy *region)
 {
@@ -1493,13 +1440,13 @@ static void
 emit_copy_buffer_to_image_rcl(struct v3dv_job *job,
                               struct v3dv_image *image,
                               struct v3dv_buffer *buffer,
-                              struct fake_framebuffer *framebuffer,
+                              struct framebuffer_data *framebuffer,
                               const VkBufferImageCopy *region)
 {
    struct v3dv_cl *rcl = emit_rcl_prologue(job, framebuffer, NULL, NULL,
                                            region->imageSubresource.aspectMask,
                                            0, 0);
-   for (int layer = 0; layer < framebuffer->fb.layers; layer++)
+   for (int layer = 0; layer < job->frame_tiling.layers; layer++)
       emit_copy_buffer_to_layer(job, image, buffer, framebuffer, layer, region);
    cl_emit(rcl, END_OF_RENDERING, end);
 }
@@ -1520,31 +1467,14 @@ copy_buffer_to_image_tlb(struct v3dv_cmd_buffer *cmd_buffer,
    uint32_t num_layers = region->imageSubresource.layerCount;
    assert(num_layers > 0);
 
-   struct fake_framebuffer framebuffer;
-   setup_framebuffer_params(&framebuffer,
-                            region->imageExtent.width,
-                            region->imageExtent.height,
-                            num_layers, internal_bpp, internal_type);
-
-   /* Limit supertile coverage to the requested region  */
-   uint32_t supertile_w_in_pixels =
-      framebuffer.tiling.tile_width * framebuffer.tiling.supertile_width;
-   uint32_t supertile_h_in_pixels =
-      framebuffer.tiling.tile_height * framebuffer.tiling.supertile_height;
-   const uint32_t max_render_x =
-      region->imageOffset.x + region->imageExtent.width - 1;
-   const uint32_t max_render_y =
-      region->imageOffset.y + region->imageExtent.height - 1;
-
-   assert(region->imageOffset.x == 0 && region->imageOffset.y == 0);
-   framebuffer.min_x_supertile = 0;
-   framebuffer.min_y_supertile = 0;
-   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, -1);
    v3dv_cmd_buffer_start_frame(cmd_buffer,
-                               &framebuffer.fb, &framebuffer.tiling, 1);
+                               region->imageExtent.width,
+                               region->imageExtent.height,
+                               num_layers, 1, internal_bpp);
+
+   struct framebuffer_data framebuffer;
+   setup_framebuffer_data(&framebuffer, internal_type, &job->frame_tiling);
 
    v3dv_job_emit_binning_flush(job);
    emit_copy_buffer_to_image_rcl(job, image, buffer, &framebuffer, region);
index c0f1fe2..be7290e 100644 (file)
@@ -409,7 +409,11 @@ struct v3dv_framebuffer {
 };
 
 struct v3dv_frame_tiling {
+   uint32_t width;
+   uint32_t height;
+   uint32_t render_target_count;
    uint32_t internal_bpp;
+   uint32_t layers;
    uint32_t tile_width;
    uint32_t tile_height;
    uint32_t draw_tiles_x;
@@ -422,11 +426,6 @@ struct v3dv_frame_tiling {
 
 uint8_t v3dv_framebuffer_compute_internal_bpp(const struct v3dv_framebuffer *framebuffer,
                                               const struct v3dv_subpass *subpass);
-void v3dv_framebuffer_compute_tiling_params(const struct v3dv_framebuffer *framebuffer,
-                                            const struct v3dv_subpass *subpass,
-                                            uint8_t internal_bpp,
-                                            struct v3dv_frame_tiling *tiling);
-
 
 struct v3dv_cmd_pool {
    VkAllocationCallbacks alloc;
@@ -646,9 +645,11 @@ struct v3dv_job *v3dv_cmd_buffer_start_job(struct v3dv_cmd_buffer *cmd_buffer,
                                            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,
-                                 const struct v3dv_frame_tiling *tiling,
-                                 int32_t num_render_targets);
+                                 uint32_t width,
+                                 uint32_t height,
+                                 uint32_t layers,
+                                 uint32_t render_target_count,
+                                 uint8_t max_internal_bpp);
 
 void v3dv_render_pass_setup_render_target(struct v3dv_cmd_buffer *cmd_buffer,
                                           int rt,