Mesa (main): vulkan: Add a vk_image_view struct

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Aug 17 21:47:45 UTC 2021


Module: Mesa
Branch: main
Commit: 9cc004b3d0c0acb7057f408b9e954607fb18c69c
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=9cc004b3d0c0acb7057f408b9e954607fb18c69c

Author: Jason Ekstrand <jason at jlekstrand.net>
Date:   Wed Jul 21 22:02:14 2021 -0500

vulkan: Add a vk_image_view struct

Reviewed-by: Iago Toral Quiroga <itoral at igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12023>

---

 src/vulkan/util/vk_image.c | 181 +++++++++++++++++++++++++++++++++++++++++++++
 src/vulkan/util/vk_image.h |  96 ++++++++++++++++++++++++
 2 files changed, 277 insertions(+)

diff --git a/src/vulkan/util/vk_image.c b/src/vulkan/util/vk_image.c
index 89717739e2e..2e1f4add048 100644
--- a/src/vulkan/util/vk_image.c
+++ b/src/vulkan/util/vk_image.c
@@ -217,3 +217,184 @@ vk_image_expand_aspect_mask(const struct vk_image *image,
       return aspect_mask;
    }
 }
+
+static VkComponentSwizzle
+remap_swizzle(VkComponentSwizzle swizzle, VkComponentSwizzle component)
+{
+   return swizzle == VK_COMPONENT_SWIZZLE_IDENTITY ? component : swizzle;
+}
+
+void
+vk_image_view_init(struct vk_device *device,
+                   struct vk_image_view *image_view,
+                   const VkImageViewCreateInfo *pCreateInfo)
+{
+   vk_object_base_init(device, &image_view->base, VK_OBJECT_TYPE_IMAGE_VIEW);
+
+   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO);
+   VK_FROM_HANDLE(vk_image, image, pCreateInfo->image);
+
+   image_view->create_flags = pCreateInfo->flags;
+   image_view->image = image;
+   image_view->view_type = pCreateInfo->viewType;
+
+   switch (image_view->view_type) {
+   case VK_IMAGE_VIEW_TYPE_1D:
+   case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
+      assert(image->image_type == VK_IMAGE_TYPE_1D);
+      break;
+   case VK_IMAGE_VIEW_TYPE_2D:
+   case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
+      if (image->create_flags & VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT)
+         assert(image->image_type == VK_IMAGE_TYPE_3D);
+      else
+         assert(image->image_type == VK_IMAGE_TYPE_2D);
+      break;
+   case VK_IMAGE_VIEW_TYPE_3D:
+      assert(image->image_type == VK_IMAGE_TYPE_3D);
+      break;
+   case VK_IMAGE_VIEW_TYPE_CUBE:
+   case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
+      assert(image->image_type == VK_IMAGE_TYPE_2D);
+      assert(image->create_flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT);
+      break;
+   default:
+      unreachable("Invalid image view type");
+   }
+
+   const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
+
+   image_view->aspects = vk_image_expand_aspect_mask(image, range->aspectMask);
+
+   /* From the Vulkan 1.2.184 spec:
+    *
+    *    "If the image has a multi-planar format and
+    *    subresourceRange.aspectMask is VK_IMAGE_ASPECT_COLOR_BIT, and image
+    *    has been created with a usage value not containing any of the
+    *    VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR,
+    *    VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR,
+    *    VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR,
+    *    VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR,
+    *    VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR, and
+    *    VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR flags, then the format must
+    *    be identical to the image format, and the sampler to be used with the
+    *    image view must enable sampler Y′CBCR conversion."
+    *
+    * Since no one implements video yet, we can ignore the bits about video
+    * create flags and assume YCbCr formats match.
+    */
+   if ((image->aspects & VK_IMAGE_ASPECT_PLANE_1_BIT) &&
+       (range->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT))
+      assert(pCreateInfo->format == image->format);
+
+   /* From the Vulkan 1.2.184 spec:
+    *
+    *    "Each depth/stencil format is only compatible with itself."
+    */
+   if (image_view->aspects & (VK_IMAGE_ASPECT_DEPTH_BIT |
+                              VK_IMAGE_ASPECT_STENCIL_BIT))
+      assert(pCreateInfo->format == image->format);
+
+   if (!(image->create_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT))
+      assert(pCreateInfo->format == image->format);
+
+   /* Restrict the format to only the planes chosen.
+    *
+    * For combined depth and stencil images, this means the depth-only or
+    * stencil-only format if only one aspect is chosen and the full combined
+    * format if both aspects are chosen.
+    *
+    * For single-plane color images, we just take the format as-is.  For
+    * multi-plane views of multi-plane images, this means we want the full
+    * multi-plane format.  For single-plane views of multi-plane images, we
+    * want a format compatible with the one plane.  Fortunately, this is
+    * already what the client gives us.  The Vulkan 1.2.184 spec says:
+    *
+    *    "If image was created with the VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT and
+    *    the image has a multi-planar format, and if
+    *    subresourceRange.aspectMask is VK_IMAGE_ASPECT_PLANE_0_BIT,
+    *    VK_IMAGE_ASPECT_PLANE_1_BIT, or VK_IMAGE_ASPECT_PLANE_2_BIT, format
+    *    must be compatible with the corresponding plane of the image, and the
+    *    sampler to be used with the image view must not enable sampler Y′CBCR
+    *    conversion."
+    */
+   if (image_view->aspects == VK_IMAGE_ASPECT_STENCIL_BIT) {
+      image_view->format = vk_format_stencil_only(pCreateInfo->format);
+   } else if (image_view->aspects == VK_IMAGE_ASPECT_DEPTH_BIT) {
+      image_view->format = vk_format_depth_only(pCreateInfo->format);
+   } else {
+      image_view->format = pCreateInfo->format;
+   }
+
+   image_view->swizzle = (VkComponentMapping) {
+      .r = remap_swizzle(pCreateInfo->components.r, VK_COMPONENT_SWIZZLE_R),
+      .g = remap_swizzle(pCreateInfo->components.g, VK_COMPONENT_SWIZZLE_G),
+      .b = remap_swizzle(pCreateInfo->components.b, VK_COMPONENT_SWIZZLE_B),
+      .a = remap_swizzle(pCreateInfo->components.a, VK_COMPONENT_SWIZZLE_A),
+   };
+
+   assert(range->layerCount > 0);
+   assert(range->baseMipLevel < image->mip_levels);
+
+   image_view->base_mip_level = range->baseMipLevel;
+   image_view->level_count = vk_image_subresource_level_count(image, range);
+   image_view->base_array_layer = range->baseArrayLayer;
+   image_view->layer_count = vk_image_subresource_layer_count(image, range);
+
+   image_view->extent =
+      vk_image_mip_level_extent(image, image_view->base_mip_level);
+
+   assert(image_view->base_mip_level + image_view->level_count
+          <= image->mip_levels);
+   switch (image->image_type) {
+   default:
+      unreachable("bad VkImageType");
+   case VK_IMAGE_TYPE_1D:
+   case VK_IMAGE_TYPE_2D:
+      assert(image_view->base_array_layer + image_view->layer_count
+             <= image->array_layers);
+      break;
+   case VK_IMAGE_TYPE_3D:
+      assert(image_view->base_array_layer + image_view->layer_count
+             <= image_view->extent.depth);
+      break;
+   }
+
+   const VkImageUsageFlags image_usage =
+      vk_image_usage(image, image_view->aspects);
+   const VkImageViewUsageCreateInfo *usage_info =
+      vk_find_struct_const(pCreateInfo, IMAGE_VIEW_USAGE_CREATE_INFO);
+   image_view->usage = usage_info ? usage_info->usage : image_usage;
+   assert(!(image_view->usage & ~image_usage));
+}
+
+void
+vk_image_view_finish(struct vk_image_view *image_view)
+{
+   vk_object_base_finish(&image_view->base);
+}
+
+void *
+vk_image_view_create(struct vk_device *device,
+                     const VkImageViewCreateInfo *pCreateInfo,
+                     const VkAllocationCallbacks *alloc,
+                     size_t size)
+{
+   struct vk_image_view *image_view =
+      vk_zalloc2(&device->alloc, alloc, size, 8,
+                 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (image_view == NULL)
+      return NULL;
+
+   vk_image_view_init(device, image_view, pCreateInfo);
+
+   return image_view;
+}
+
+void
+vk_image_view_destroy(struct vk_device *device,
+                      const VkAllocationCallbacks *alloc,
+                      struct vk_image_view *image_view)
+{
+   vk_object_free(device, alloc, image_view);
+}
diff --git a/src/vulkan/util/vk_image.h b/src/vulkan/util/vk_image.h
index ff8c3523693..b28c6e3c777 100644
--- a/src/vulkan/util/vk_image.h
+++ b/src/vulkan/util/vk_image.h
@@ -58,6 +58,8 @@ struct vk_image {
    uint64_t android_external_format;
 #endif
 };
+VK_DEFINE_NONDISP_HANDLE_CASTS(vk_image, base, VkImage,
+                               VK_OBJECT_TYPE_IMAGE);
 
 void vk_image_init(struct vk_device *device,
                    struct vk_image *image,
@@ -107,6 +109,100 @@ vk_image_subresource_level_count(const struct vk_image *image,
           image->mip_levels - range->baseMipLevel : range->levelCount;
 }
 
+struct vk_image_view {
+   struct vk_object_base base;
+
+   VkImageViewCreateFlags create_flags;
+   struct vk_image *image;
+   VkImageViewType view_type;
+
+   /** Image view format, relative to the selected aspects
+    *
+    * For a depth/stencil image:
+    *
+    *  - If vk_image_view::aspects contains both depth and stencil, this will
+    *    be the full depth/stencil format of the image.
+    *
+    *  - If only one aspect is selected, this will be the depth-only or
+    *    stencil-only format, as per the selected aspect.
+    *
+    * For color images, we have three cases:
+    *
+    *  1. It's a single-plane image in which case this is the unmodified
+    *     format provided to VkImageViewCreateInfo::format.
+    *
+    *  2. It's a YCbCr view of a multi-plane image in which case the
+    *     client will have asked for VK_IMAGE_ASPECT_COLOR_BIT and the
+    *     format provided will be the full planar format.  In this case,
+    *     the format will be the full format containing all the planes.
+    *
+    *  3. It's a single-plane view of a multi-plane image in which case
+    *     the client will have asked for VK_IMAGE_ASPECT_PLANE_N_BIT and
+    *     will have provided a format compatible with that specific
+    *     plane of the multi-planar format.  In this case, the format will be
+    *     the plane-compatible format requested by the client.
+    */
+   VkFormat format;
+
+   /* Component mapping, aka swizzle
+    *
+    * Unlike the swizzle provided via VkImageViewCreateInfo::components, this
+    * will never contain VK_COMPONENT_SWIZZLE_IDENTITY.  It will be resolved
+    * to VK_COMPONENT_SWIZZLE_R/G/B/A, as appropriate.
+    */
+   VkComponentMapping swizzle;
+
+   /** Aspects from the image represented by this view
+    *
+    * For depth/stencil images, this is the aspectMask provided by
+    * VkImageViewCreateinfo::subresourceRange::aspectMask.
+    *
+    * For color images, we have three cases:
+    *
+    *  1. It's a single-plane image in which case this only aspect is
+    *     VK_IMAGE_ASPECT_COLOR_BIT.
+    *
+    *  2. It's a YCbCr view of a multi-plane image in which case the
+    *     client will have asked for VK_IMAGE_ASPECT_COLOR_BIT and the
+    *     format provided will be the full planar format.  In this case,
+    *     aspects will be the full set of plane aspects in the image.
+    *
+    *  3. It's a single-plane view of a multi-plane image in which case
+    *     the client will have asked for VK_IMAGE_ASPECT_PLANE_N_BIT and
+    *     will have provided a format compatible with that specific
+    *     plane of the multi-planar format.  In this case, aspects will be
+    *     VK_IMAGE_ASPECT_PLANE_N_BIT where N is the selected plane.
+    *
+    * This seems almost backwards from the API but ensures that
+    * vk_image_view::aspects is always a subset of vk_image::aspects.
+    */
+   VkImageAspectFlags aspects;
+
+   uint32_t base_mip_level;
+   uint32_t level_count;
+   uint32_t base_array_layer;
+   uint32_t layer_count;
+
+   /* Image extent at LOD 0 */
+   VkExtent3D extent;
+
+   /* VK_KHR_maintenance2 */
+   VkImageUsageFlags usage;
+};
+
+void vk_image_view_init(struct vk_device *device,
+                        struct vk_image_view *image_view,
+                        const VkImageViewCreateInfo *pCreateInfo);
+void vk_image_view_finish(struct vk_image_view *image_view);
+
+void *vk_image_view_create(struct vk_device *device,
+                           const VkImageViewCreateInfo *pCreateInfo,
+                           const VkAllocationCallbacks *alloc,
+                           size_t size);
+void vk_image_view_destroy(struct vk_device *device,
+                           const VkAllocationCallbacks *alloc,
+                           struct vk_image_view *image_view);
+
 #ifdef __cplusplus
 }
 #endif



More information about the mesa-commit mailing list