lavapipe: allocate image and image view planes.
authorDave Airlie <airlied@redhat.com>
Fri, 6 Oct 2023 05:37:38 +0000 (15:37 +1000)
committerMarge Bot <emma+marge@anholt.net>
Tue, 10 Oct 2023 04:37:07 +0000 (04:37 +0000)
This allocate planes and handles disjoint.

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25609>

src/gallium/frontends/lavapipe/lvp_device.c
src/gallium/frontends/lavapipe/lvp_image.c
src/gallium/frontends/lavapipe/lvp_private.h

index b86489d..ddb31c5 100644 (file)
@@ -2074,11 +2074,22 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_BindImageMemory2(VkDevice _device,
       if (!did_bind) {
          uint64_t offset_B = 0;
          VkResult result;
-
-         result = lvp_image_plane_bind(device, &image->planes[0],
-                                       mem, bind_info->memoryOffset, &offset_B);
-         if (result != VK_SUCCESS)
-            return result;
+         if (image->disjoint) {
+            const VkBindImagePlaneMemoryInfo *plane_info =
+               vk_find_struct_const(pBindInfos[i].pNext, BIND_IMAGE_PLANE_MEMORY_INFO);
+            uint8_t plane = lvp_image_aspects_to_plane(image, plane_info->planeAspect);
+            result = lvp_image_plane_bind(device, &image->planes[plane],
+                                          mem, bind_info->memoryOffset, &offset_B);
+            if (result != VK_SUCCESS)
+               return result;
+         } else {
+            for (unsigned plane = 0; plane < image->plane_count; plane++) {
+               result = lvp_image_plane_bind(device, &image->planes[plane],
+                                             mem, bind_info->memoryOffset, &offset_B);
+               if (result != VK_SUCCESS)
+                  return result;
+            }
+         }
       }
    }
    return VK_SUCCESS;
index 19fdba7..8dbcd28 100644 (file)
@@ -43,10 +43,20 @@ lvp_image_create(VkDevice _device,
       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
 
    image->alignment = 16;
+   image->plane_count = vk_format_get_plane_count(pCreateInfo->format);
+   image->disjoint = image->plane_count > 1 &&
+                     (pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT);
 
-   {
+   const struct vk_format_ycbcr_info *ycbcr_info =
+      vk_format_get_ycbcr_info(pCreateInfo->format);
+   for (unsigned p = 0; p < image->plane_count; p++) {
       struct pipe_resource template;
-      VkFormat format = pCreateInfo->format;
+      VkFormat format = ycbcr_info ?
+         ycbcr_info->planes[p].format : pCreateInfo->format;
+      const uint8_t width_scale = ycbcr_info ?
+         ycbcr_info->planes[p].denominator_scales[0] : 1;
+      const uint8_t height_scale = ycbcr_info ?
+         ycbcr_info->planes[p].denominator_scales[1] : 1;
       memset(&template, 0, sizeof(template));
 
       template.screen = device->pscreen;
@@ -93,20 +103,20 @@ lvp_image_create(VkDevice _device,
                                 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))
          template.bind |= PIPE_BIND_SHADER_IMAGE;
 
-      template.width0 = pCreateInfo->extent.width;
-      template.height0 = pCreateInfo->extent.height;
+      template.width0 = pCreateInfo->extent.width / width_scale;
+      template.height0 = pCreateInfo->extent.height / height_scale;
       template.depth0 = pCreateInfo->extent.depth;
       template.array_size = pCreateInfo->arrayLayers;
       template.last_level = pCreateInfo->mipLevels - 1;
       template.nr_samples = pCreateInfo->samples;
       template.nr_storage_samples = pCreateInfo->samples;
-      image->planes[0].bo = device->pscreen->resource_create_unbacked(device->pscreen,
+      image->planes[p].bo = device->pscreen->resource_create_unbacked(device->pscreen,
                                                                       &template,
-                                                                      &image->planes[0].size);
-      if (!image->planes[0].bo)
+                                                                      &image->planes[p].size);
+      if (!image->planes[p].bo)
          return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
 
-      image->size += image->planes[0].size;
+      image->size += image->planes[p].size;
    }
    *pImage = lvp_image_to_handle(image);
 
@@ -170,7 +180,8 @@ lvp_DestroyImage(VkDevice _device, VkImage _image,
 
    if (!_image)
      return;
-   pipe_resource_reference(&image->planes[0].bo, NULL);
+   for (unsigned p = 0; p < image->plane_count; p++)
+      pipe_resource_reference(&image->planes[p].bo, NULL);
    vk_image_destroy(&device->vk, pAllocator, &image->vk);
 }
 
@@ -191,7 +202,7 @@ static inline char conv_depth_swiz(char swiz) {
 }
 
 static struct pipe_sampler_view *
-lvp_create_samplerview(struct pipe_context *pctx, struct lvp_image_view *iv)
+lvp_create_samplerview(struct pipe_context *pctx, struct lvp_image_view *iv, VkFormat plane_format, unsigned image_plane)
 {
    if (!iv)
       return NULL;
@@ -199,13 +210,13 @@ lvp_create_samplerview(struct pipe_context *pctx, struct lvp_image_view *iv)
    struct pipe_sampler_view templ;
    enum pipe_format pformat;
    if (iv->vk.aspects == VK_IMAGE_ASPECT_DEPTH_BIT)
-      pformat = lvp_vk_format_to_pipe_format(iv->vk.format);
+      pformat = lvp_vk_format_to_pipe_format(plane_format);
    else if (iv->vk.aspects == VK_IMAGE_ASPECT_STENCIL_BIT)
-      pformat = util_format_stencil_only(lvp_vk_format_to_pipe_format(iv->vk.format));
+      pformat = util_format_stencil_only(lvp_vk_format_to_pipe_format(plane_format));
    else
-      pformat = lvp_vk_format_to_pipe_format(iv->vk.format);
+      pformat = lvp_vk_format_to_pipe_format(plane_format);
    u_sampler_view_default_template(&templ,
-                                   iv->image->planes[0].bo,
+                                   iv->image->planes[image_plane].bo,
                                    pformat);
    if (iv->vk.view_type == VK_IMAGE_VIEW_TYPE_1D)
       templ.target = PIPE_TEXTURE_1D;
@@ -238,23 +249,23 @@ lvp_create_samplerview(struct pipe_context *pctx, struct lvp_image_view *iv)
       templ.swizzle_a = conv_depth_swiz(templ.swizzle_a);
    }
 
-   return pctx->create_sampler_view(pctx, iv->image->planes[0].bo, &templ);
+   return pctx->create_sampler_view(pctx, iv->image->planes[image_plane].bo, &templ);
 }
 
 static struct pipe_image_view
-lvp_create_imageview(const struct lvp_image_view *iv)
+lvp_create_imageview(const struct lvp_image_view *iv, VkFormat plane_format, unsigned image_plane)
 {
    struct pipe_image_view view = {0};
    if (!iv)
       return view;
 
-   view.resource = iv->image->planes[0].bo;
+   view.resource = iv->image->planes[image_plane].bo;
    if (iv->vk.aspects == VK_IMAGE_ASPECT_DEPTH_BIT)
-      view.format = lvp_vk_format_to_pipe_format(iv->vk.format);
+      view.format = lvp_vk_format_to_pipe_format(plane_format);
    else if (iv->vk.aspects == VK_IMAGE_ASPECT_STENCIL_BIT)
-      view.format = util_format_stencil_only(lvp_vk_format_to_pipe_format(iv->vk.format));
+      view.format = util_format_stencil_only(lvp_vk_format_to_pipe_format(plane_format));
    else
-      view.format = lvp_vk_format_to_pipe_format(iv->vk.format);
+      view.format = lvp_vk_format_to_pipe_format(plane_format);
 
    if (iv->vk.view_type == VK_IMAGE_VIEW_TYPE_3D) {
       view.u.tex.first_layer = iv->vk.storage.z_slice_offset;
@@ -286,16 +297,45 @@ lvp_CreateImageView(VkDevice _device,
    view->image = image;
    view->surface = NULL;
 
+   if (image->vk.aspects & (VK_IMAGE_ASPECT_DEPTH_BIT |
+                            VK_IMAGE_ASPECT_STENCIL_BIT)) {
+      assert(image->plane_count == 1);
+      assert(lvp_image_aspects_to_plane(image, view->vk.aspects) == 0);
+      view->plane_count = 1;
+      view->planes[0].image_plane = 0;
+   } else {
+      /* For other formats, retrieve the plane count from the aspect mask
+       * and then walk through the aspect mask to map each image plane
+       * to its corresponding view plane
+       */
+      assert(util_bitcount(view->vk.aspects) ==
+             vk_format_get_plane_count(view->vk.format));
+      view->plane_count = 0;
+      u_foreach_bit(aspect_bit, view->vk.aspects) {
+         uint8_t image_plane = lvp_image_aspects_to_plane(image, 1u << aspect_bit);
+         view->planes[view->plane_count++].image_plane = image_plane;
+      }
+   }
+
    simple_mtx_lock(&device->queue.lock);
 
-   if (image->planes[0].bo->bind & PIPE_BIND_SHADER_IMAGE) {
-      view->planes[0].iv = lvp_create_imageview(view);
-      view->planes[0].image_handle = (void *)(uintptr_t)device->queue.ctx->create_image_handle(device->queue.ctx, &view->planes[0].iv);
-   }
+   for (unsigned view_plane = 0; view_plane < view->plane_count; view_plane++) {
+      const uint8_t image_plane = view->planes[view_plane].image_plane;
+      const struct vk_format_ycbcr_info *ycbcr_info =
+         vk_format_get_ycbcr_info(view->vk.format);
+      assert(ycbcr_info || view_plane == 0);
+      VkFormat plane_format = ycbcr_info ?
+         ycbcr_info->planes[view_plane].format : view->vk.format;
+
+      if (image->planes[image_plane].bo->bind & PIPE_BIND_SHADER_IMAGE) {
+         view->planes[view_plane].iv = lvp_create_imageview(view, plane_format, image_plane);
+         view->planes[view_plane].image_handle = (void *)(uintptr_t)device->queue.ctx->create_image_handle(device->queue.ctx, &view->planes[view_plane].iv);
+      }
 
-   if (image->planes[0].bo->bind & PIPE_BIND_SAMPLER_VIEW) {
-      view->planes[0].sv = lvp_create_samplerview(device->queue.ctx, view);
-      view->planes[0].texture_handle = (void *)(uintptr_t)device->queue.ctx->create_texture_handle(device->queue.ctx, view->planes[0].sv, NULL);
+      if (image->planes[image_plane].bo->bind & PIPE_BIND_SAMPLER_VIEW) {
+         view->planes[view_plane].sv = lvp_create_samplerview(device->queue.ctx, view, plane_format, image_plane);
+         view->planes[view_plane].texture_handle = (void *)(uintptr_t)device->queue.ctx->create_texture_handle(device->queue.ctx, view->planes[view_plane].sv, NULL);
+      }
    }
 
    simple_mtx_unlock(&device->queue.lock);
@@ -317,11 +357,12 @@ lvp_DestroyImageView(VkDevice _device, VkImageView _iview,
 
    simple_mtx_lock(&device->queue.lock);
 
-   device->queue.ctx->delete_image_handle(device->queue.ctx, (uint64_t)(uintptr_t)iview->planes[0].image_handle);
-
-   pipe_sampler_view_reference(&iview->planes[0].sv, NULL);
-   device->queue.ctx->delete_texture_handle(device->queue.ctx, (uint64_t)(uintptr_t)iview->planes[0].texture_handle);
+   for (uint8_t plane = 0; plane < iview->plane_count; plane++) {
+      device->queue.ctx->delete_image_handle(device->queue.ctx, (uint64_t)(uintptr_t)iview->planes[plane].image_handle);
 
+      pipe_sampler_view_reference(&iview->planes[plane].sv, NULL);
+      device->queue.ctx->delete_texture_handle(device->queue.ctx, (uint64_t)(uintptr_t)iview->planes[plane].texture_handle);
+   }
    simple_mtx_unlock(&device->queue.lock);
 
    pipe_surface_reference(&iview->surface, NULL);
index 92f799e..75d7a52 100644 (file)
@@ -263,7 +263,9 @@ struct lvp_image {
    struct vk_image vk;
    VkDeviceSize size;
    uint32_t alignment;
-   struct lvp_image_plane planes[1];
+   bool disjoint;
+   uint8_t plane_count;
+   struct lvp_image_plane planes[3];
 };
 
 struct lvp_image_view {
@@ -277,11 +279,12 @@ struct lvp_image_view {
 
    uint8_t plane_count;
    struct {
+      unsigned image_plane;
       struct pipe_sampler_view *sv;
       struct pipe_image_view iv;
       struct lp_texture_handle *texture_handle;
       struct lp_texture_handle *image_handle;
-   } planes[1];
+   } planes[3];
 };
 
 struct lvp_sampler {
@@ -690,6 +693,25 @@ lvp_vk_format_to_pipe_format(VkFormat format)
    return vk_format_to_pipe_format(format);
 }
 
+static inline uint8_t
+lvp_image_aspects_to_plane(ASSERTED const struct lvp_image *image,
+                           VkImageAspectFlags aspectMask)
+{
+   /* Verify that the aspects are actually in the image */
+   assert(!(aspectMask & ~image->vk.aspects));
+
+   /* Must only be one aspect unless it's depth/stencil */
+   assert(aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT |
+                         VK_IMAGE_ASPECT_STENCIL_BIT) ||
+          util_bitcount(aspectMask) == 1);
+
+   switch(aspectMask) {
+   case VK_IMAGE_ASPECT_PLANE_1_BIT: return 1;
+   case VK_IMAGE_ASPECT_PLANE_2_BIT: return 2;
+   default: return 0;
+   }
+}
+
 void
 lvp_pipeline_destroy(struct lvp_device *device, struct lvp_pipeline *pipeline, bool locked);