v3dv: consider MSAA when computing frame tiling

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 1f3d171..5cd5a70 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -445,7 +445,8 @@
                          uint32_t height,
                          uint32_t layers,
                          uint32_t render_target_count,
-                         uint8_t max_internal_bpp)
+                         uint8_t max_internal_bpp,
+                         bool msaa)
 {
    static const uint8_t tile_sizes[] = {
       64, 64,
@@ -462,16 +463,18 @@
    tiling->height = height;
    tiling->layers = layers;
    tiling->render_target_count = render_target_count;
+   tiling->msaa = msaa;
 
    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;
 
+   if (msaa)
+      tile_size_index += 2;
+
    tiling->internal_bpp = max_internal_bpp;
    tile_size_index += tiling->internal_bpp;
    assert(tile_size_index < ARRAY_SIZE(tile_sizes));
@@ -511,7 +514,8 @@
                      uint32_t height,
                      uint32_t layers,
                      uint32_t render_target_count,
-                     uint8_t max_internal_bpp)
+                     uint8_t max_internal_bpp,
+                     bool msaa)
 {
    assert(job);
 
@@ -519,7 +523,7 @@
    const struct v3dv_frame_tiling *tiling =
       job_compute_frame_tiling(job,
                                width, height, layers,
-                               render_target_count, max_internal_bpp);
+                               render_target_count, max_internal_bpp, msaa);
 
    v3dv_cl_ensure_space_with_branch(&job->bcl, 256);
    v3dv_return_if_oom(NULL, job);
@@ -2115,15 +2119,18 @@
 
       const struct v3dv_framebuffer *framebuffer = state->framebuffer;
 
-      const uint8_t internal_bpp =
-         v3dv_framebuffer_compute_internal_bpp(framebuffer, subpass);
+      uint8_t internal_bpp;
+      bool msaa;
+      v3dv_framebuffer_compute_internal_bpp_msaa(framebuffer, subpass,
+                                                 &internal_bpp, &msaa);
 
       v3dv_job_start_frame(job,
                            framebuffer->width,
                            framebuffer->height,
                            framebuffer->layers,
                            subpass->color_count,
-                           internal_bpp);
+                           internal_bpp,
+                           msaa);
 
       /* FIXME: we don't suppport resolve attachments yet */
       assert(subpass->resolve_attachments == NULL);
diff --git a/src/broadcom/vulkan/v3dv_device.c b/src/broadcom/vulkan/v3dv_device.c
index 7e819c5..0494303 100644
--- a/src/broadcom/vulkan/v3dv_device.c
+++ b/src/broadcom/vulkan/v3dv_device.c
@@ -1917,15 +1917,20 @@
 
 /**
  * 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
+ * a particular subpass and checks if any of those render targets are
+ * multisampled. 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)
+void
+v3dv_framebuffer_compute_internal_bpp_msaa(
+   const struct v3dv_framebuffer *framebuffer,
+   const struct v3dv_subpass *subpass,
+   uint8_t *max_bpp,
+   bool *msaa)
 {
    STATIC_ASSERT(RENDER_TARGET_MAXIMUM_32BPP == 0);
-   uint8_t max_bpp = RENDER_TARGET_MAXIMUM_32BPP;
+   *max_bpp = RENDER_TARGET_MAXIMUM_32BPP;
+   *msaa = false;
 
    if (subpass) {
       for (uint32_t i = 0; i < subpass->color_count; i++) {
@@ -1937,10 +1942,22 @@
          assert(att);
 
          if (att->aspects & VK_IMAGE_ASPECT_COLOR_BIT)
-            max_bpp = MAX2(max_bpp, att->internal_bpp);
+            *max_bpp = MAX2(*max_bpp, att->internal_bpp);
+
+         if (att->image->samples > VK_SAMPLE_COUNT_1_BIT)
+            *msaa = true;
       }
 
-      return max_bpp;
+      if (!*msaa && subpass->ds_attachment.attachment != VK_ATTACHMENT_UNUSED) {
+         const struct v3dv_image_view *att =
+            framebuffer->attachments[subpass->ds_attachment.attachment];
+         assert(att);
+
+         if (att->image->samples > VK_SAMPLE_COUNT_1_BIT)
+            *msaa = true;
+      }
+
+      return;
    }
 
    assert(framebuffer->attachment_count <= 4);
@@ -1949,10 +1966,13 @@
       assert(att);
 
       if (att->aspects & VK_IMAGE_ASPECT_COLOR_BIT)
-         max_bpp = MAX2(max_bpp, att->internal_bpp);
+         *max_bpp = MAX2(*max_bpp, att->internal_bpp);
+
+      if (att->image->samples > VK_SAMPLE_COUNT_1_BIT)
+         *msaa = true;
    }
 
-   return max_bpp;
+   return;
 }
 
 VkResult
diff --git a/src/broadcom/vulkan/v3dv_image.c b/src/broadcom/vulkan/v3dv_image.c
index 6bf6405..fb2da0d 100644
--- a/src/broadcom/vulkan/v3dv_image.c
+++ b/src/broadcom/vulkan/v3dv_image.c
@@ -114,7 +114,9 @@
    uint32_t block_width = vk_format_get_blockwidth(image->vk_format);
    uint32_t block_height = vk_format_get_blockheight(image->vk_format);
 
-   bool msaa = image->samples > VK_SAMPLE_COUNT_1_BIT;
+   assert(image->samples == VK_SAMPLE_COUNT_1_BIT ||
+          image->samples == VK_SAMPLE_COUNT_4_BIT);
+   bool msaa = image->samples != VK_SAMPLE_COUNT_1_BIT;
 
    bool uif_top = msaa;
 
@@ -328,6 +330,9 @@
    if (!image)
       return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
 
+   assert(pCreateInfo->samples == VK_SAMPLE_COUNT_1_BIT ||
+          pCreateInfo->samples == VK_SAMPLE_COUNT_4_BIT);
+
    image->type = pCreateInfo->imageType;
    image->extent = pCreateInfo->extent;
    image->vk_format = pCreateInfo->format;
diff --git a/src/broadcom/vulkan/v3dv_meta_clear.c b/src/broadcom/vulkan/v3dv_meta_clear.c
index 9a7020f..07d2a20 100644
--- a/src/broadcom/vulkan/v3dv_meta_clear.c
+++ b/src/broadcom/vulkan/v3dv_meta_clear.c
@@ -1300,15 +1300,17 @@
       }
    }
 
-   const uint8_t internal_bpp =
-      v3dv_framebuffer_compute_internal_bpp(framebuffer, subpass);
+   uint8_t internal_bpp;
+   bool msaa;
+   v3dv_framebuffer_compute_internal_bpp_msaa(framebuffer, subpass,
+                                              &internal_bpp, &msaa);
 
    v3dv_job_start_frame(job,
                         framebuffer->width,
                         framebuffer->height,
                         framebuffer->layers,
                         color_attachment_count,
-                        internal_bpp);
+                        internal_bpp, msaa);
 
    struct v3dv_cl *rcl = &job->rcl;
    v3dv_cl_ensure_space_with_branch(rcl, 200 +
diff --git a/src/broadcom/vulkan/v3dv_meta_copy.c b/src/broadcom/vulkan/v3dv_meta_copy.c
index 3f1f15b..c930669 100644
--- a/src/broadcom/vulkan/v3dv_meta_copy.c
+++ b/src/broadcom/vulkan/v3dv_meta_copy.c
@@ -691,7 +691,7 @@
    const uint32_t width = DIV_ROUND_UP(region->imageExtent.width, block_w);
    const uint32_t height = DIV_ROUND_UP(region->imageExtent.height, block_h);
 
-   v3dv_job_start_frame(job, width, height, num_layers, 1, internal_bpp);
+   v3dv_job_start_frame(job, width, height, num_layers, 1, internal_bpp, false);
 
    struct framebuffer_data framebuffer;
    setup_framebuffer_data(&framebuffer, fb_format, internal_type,
@@ -1185,7 +1185,7 @@
    const uint32_t width = DIV_ROUND_UP(region->extent.width, block_w);
    const uint32_t height = DIV_ROUND_UP(region->extent.height, block_h);
 
-   v3dv_job_start_frame(job, width, height, num_layers, 1, internal_bpp);
+   v3dv_job_start_frame(job, width, height, num_layers, 1, internal_bpp, false);
 
    struct framebuffer_data framebuffer;
    setup_framebuffer_data(&framebuffer, fb_format, internal_type,
@@ -1501,7 +1501,7 @@
             return true;
 
          /* We start a a new job for each layer so the frame "depth" is 1 */
-         v3dv_job_start_frame(job, width, height, 1, 1, internal_bpp);
+         v3dv_job_start_frame(job, width, height, 1, 1, internal_bpp, false);
 
          struct framebuffer_data framebuffer;
          setup_framebuffer_data(&framebuffer, fb_format, internal_type,
@@ -1728,7 +1728,7 @@
       uint32_t width, height;
       framebuffer_size_for_pixel_count(num_items, &width, &height);
 
-      v3dv_job_start_frame(job, width, height, 1, 1, internal_bpp);
+      v3dv_job_start_frame(job, width, height, 1, 1, internal_bpp, false);
 
       struct framebuffer_data framebuffer;
       setup_framebuffer_data(&framebuffer, vk_format, internal_type,
@@ -1917,7 +1917,7 @@
       uint32_t width, height;
       framebuffer_size_for_pixel_count(num_items, &width, &height);
 
-      v3dv_job_start_frame(job, width, height, 1, 1, internal_bpp);
+      v3dv_job_start_frame(job, width, height, 1, 1, internal_bpp, false);
 
       struct framebuffer_data framebuffer;
       setup_framebuffer_data(&framebuffer, VK_FORMAT_R8G8B8A8_UINT,
@@ -2270,7 +2270,7 @@
    const uint32_t width = DIV_ROUND_UP(region->imageExtent.width, block_w);
    const uint32_t height = DIV_ROUND_UP(region->imageExtent.height, block_h);
 
-   v3dv_job_start_frame(job, width, height, num_layers, 1, internal_bpp);
+   v3dv_job_start_frame(job, width, height, num_layers, 1, internal_bpp, false);
 
    struct framebuffer_data framebuffer;
    setup_framebuffer_data(&framebuffer, fb_format, internal_type,
diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h
index 4b4f3da..e0d7440 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -559,9 +559,10 @@
 struct v3dv_frame_tiling {
    uint32_t width;
    uint32_t height;
+   uint32_t layers;
    uint32_t render_target_count;
    uint32_t internal_bpp;
-   uint32_t layers;
+   bool     msaa;
    uint32_t tile_width;
    uint32_t tile_height;
    uint32_t draw_tiles_x;
@@ -572,8 +573,9 @@
    uint32_t frame_height_in_supertiles;
 };
 
-uint8_t v3dv_framebuffer_compute_internal_bpp(const struct v3dv_framebuffer *framebuffer,
-                                              const struct v3dv_subpass *subpass);
+void v3dv_framebuffer_compute_internal_bpp_msaa(const struct v3dv_framebuffer *framebuffer,
+                                                const struct v3dv_subpass *subpass,
+                                                uint8_t *max_bpp, bool *msaa);
 
 struct v3dv_cmd_pool {
    VkAllocationCallbacks alloc;
@@ -880,7 +882,8 @@
                           uint32_t height,
                           uint32_t layers,
                           uint32_t render_target_count,
-                          uint8_t max_internal_bpp);
+                          uint8_t max_internal_bpp,
+                          bool msaa);
 struct v3dv_job *v3dv_cmd_buffer_create_cpu_job(struct v3dv_device *device,
                                                 enum v3dv_job_type type,
                                                 struct v3dv_cmd_buffer *cmd_buffer,
diff --git a/src/broadcom/vulkan/v3dv_queue.c b/src/broadcom/vulkan/v3dv_queue.c
index a5a7164..895493f 100644
--- a/src/broadcom/vulkan/v3dv_queue.c
+++ b/src/broadcom/vulkan/v3dv_queue.c
@@ -713,7 +713,7 @@
 static void
 emit_noop_bin(struct v3dv_job *job)
 {
-   v3dv_job_start_frame(job, 1, 1, 1, 1, V3D_INTERNAL_BPP_32);
+   v3dv_job_start_frame(job, 1, 1, 1, 1, V3D_INTERNAL_BPP_32, false);
    v3dv_job_emit_binning_flush(job);
 }