/* * Copyright © 2021 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #ifndef VK_IMAGE_H #define VK_IMAGE_H #include "vk_object.h" #include "util/u_math.h" #ifdef __cplusplus extern "C" { #endif struct vk_image { struct vk_object_base base; VkImageCreateFlags create_flags; VkImageType image_type; VkFormat format; VkExtent3D extent; uint32_t mip_levels; uint32_t array_layers; VkSampleCountFlagBits samples; VkImageTiling tiling; VkImageUsageFlags usage; /* Derived from format */ VkImageAspectFlags aspects; /* VK_EXT_separate_stencil_usage */ VkImageUsageFlags stencil_usage; /* VK_KHR_external_memory */ VkExternalMemoryHandleTypeFlags external_handle_types; /* wsi_image_create_info::scanout */ bool wsi_legacy_scanout; #ifndef _WIN32 /* VK_EXT_drm_format_modifier * * Initialized by vk_image_create/init() to DRM_FORMAT_MOD_INVALID. It's * the job of the driver to parse the VK_EXT_drm_format_modifier extension * structs and choose the actual modifier. * * Must be DRM_FORMAT_MOD_INVALID unless tiling is * VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT. */ uint64_t drm_format_mod; #endif #ifdef ANDROID /* VK_ANDROID_external_memory_android_hardware_buffer */ 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, const VkImageCreateInfo *pCreateInfo); void vk_image_finish(struct vk_image *image); void *vk_image_create(struct vk_device *device, const VkImageCreateInfo *pCreateInfo, const VkAllocationCallbacks *alloc, size_t size); void vk_image_destroy(struct vk_device *device, const VkAllocationCallbacks *alloc, struct vk_image *image); void vk_image_set_format(struct vk_image *image, VkFormat format); VkImageUsageFlags vk_image_usage(const struct vk_image *image, VkImageAspectFlags aspect_mask); VkImageAspectFlags vk_image_expand_aspect_mask(const struct vk_image *image, VkImageAspectFlags aspect_mask); static inline VkExtent3D vk_image_mip_level_extent(const struct vk_image *image, uint32_t mip_level) { const VkExtent3D extent = { u_minify(image->extent.width, mip_level), u_minify(image->extent.height, mip_level), u_minify(image->extent.depth, mip_level), }; return extent; } /* This is defined as a macro so that it works for both * VkImageSubresourceRange and VkImageSubresourceLayers */ #define vk_image_subresource_layer_count(_image, _range) \ ((_range)->layerCount == VK_REMAINING_ARRAY_LAYERS ? \ (_image)->array_layers - (_range)->baseArrayLayer : (_range)->layerCount) static inline uint32_t vk_image_subresource_level_count(const struct vk_image *image, const VkImageSubresourceRange *range) { return range->levelCount == VK_REMAINING_MIP_LEVELS ? image->mip_levels - range->baseMipLevel : range->levelCount; } static inline VkExtent3D vk_image_sanitize_extent(const struct vk_image *image, const VkExtent3D imageExtent) { switch (image->image_type) { case VK_IMAGE_TYPE_1D: return (VkExtent3D) { imageExtent.width, 1, 1 }; case VK_IMAGE_TYPE_2D: return (VkExtent3D) { imageExtent.width, imageExtent.height, 1 }; case VK_IMAGE_TYPE_3D: return imageExtent; default: unreachable("invalid image type"); } } VkExtent3D vk_image_extent_to_elements(const struct vk_image *image, VkExtent3D extent); static inline VkOffset3D vk_image_sanitize_offset(const struct vk_image *image, const VkOffset3D imageOffset) { switch (image->image_type) { case VK_IMAGE_TYPE_1D: return (VkOffset3D) { imageOffset.x, 0, 0 }; case VK_IMAGE_TYPE_2D: return (VkOffset3D) { imageOffset.x, imageOffset.y, 0 }; case VK_IMAGE_TYPE_3D: return imageOffset; default: unreachable("invalid image type"); } } VkOffset3D vk_image_offset_to_elements(const struct vk_image *image, VkOffset3D offset); struct vk_image_buffer_layout { /** * VkBufferImageCopy2::bufferRowLength or * VkBufferImageCopy2::extent::width as needed. */ uint32_t row_length; /** * VkBufferImageCopy2::bufferImageHeight or * VkBufferImageCopy2::extent::height as needed. */ uint32_t image_height; /** Size of a single element (pixel or compressed block) in bytes */ uint32_t element_size_B; /** Row stride in bytes */ uint32_t row_stride_B; /** Image (or layer) stride in bytes * * For 1D or 2D array images, this is the stride in bytes between array * slices. For 3D images, this is the stride in bytes between fixed-Z * slices. */ uint64_t image_stride_B; }; struct vk_image_buffer_layout vk_image_buffer_copy_layout(const struct vk_image *image, const VkBufferImageCopy2* region); struct vk_image_view { struct vk_object_base base; VkImageViewCreateFlags create_flags; struct vk_image *image; VkImageViewType view_type; /** VkImageViewCreateInfo::format */ VkFormat format; /** 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 view_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; /* VK_EXT_image_view_min_lod */ float min_lod; /* Image extent at LOD 0 */ VkExtent3D extent; /* VK_KHR_maintenance2 */ VkImageUsageFlags usage; }; VK_DEFINE_NONDISP_HANDLE_CASTS(vk_image_view, base, VkImageView, VK_OBJECT_TYPE_IMAGE_VIEW); void vk_image_view_init(struct vk_device *device, struct vk_image_view *image_view, bool driver_internal, const VkImageViewCreateInfo *pCreateInfo); void vk_image_view_finish(struct vk_image_view *image_view); void *vk_image_view_create(struct vk_device *device, bool driver_internal, 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); static inline VkImageSubresourceRange vk_image_view_subresource_range(const struct vk_image_view *view) { VkImageSubresourceRange range = { .aspectMask = view->aspects, .baseMipLevel = view->base_mip_level, .levelCount = view->level_count, .baseArrayLayer = view->base_array_layer, .layerCount = view->layer_count, }; return range; } bool vk_image_layout_is_read_only(VkImageLayout layout, VkImageAspectFlagBits aspect); bool vk_image_layout_is_depth_only(VkImageLayout layout); VkImageUsageFlags vk_image_layout_to_usage_flags(VkImageLayout layout, VkImageAspectFlagBits aspect); VkImageLayout vk_att_ref_stencil_layout(const VkAttachmentReference2 *att_ref, const VkAttachmentDescription2 *attachments); VkImageLayout vk_att_desc_stencil_layout(const VkAttachmentDescription2 *att_desc, bool final); #ifdef __cplusplus } #endif #endif /* VK_IMAGE_H */