## 11.3. Images

Images represent multidimensional - up to 3 - arrays of data which can be used for various purposes (e.g. attachments, textures), by binding them to a graphics or compute pipeline via descriptor sets, or by directly specifying them as parameters to certain commands.

Images are created by calling:

VkResult vkCreateImage(
VkDevice                                    device,
const VkImageCreateInfo*                    pCreateInfo,
const VkAllocationCallbacks*                pAllocator,
VkImage*                                    pImage);

• device is the logical device that creates the image.
• pCreateInfo is a pointer to an instance of the VkImageCreateInfo structure containing parameters to be used to create the image.
• pAllocator controls host memory allocation as described in the Memory Allocation chapter.
• pImage points to a VkImage handle in which the resulting image object is returned.

The VkImageCreateInfo structure is defined as:

typedef struct VkImageCreateInfo {
VkStructureType          sType;
const void*              pNext;
VkImageCreateFlags       flags;
VkImageType              imageType;
VkFormat                 format;
VkExtent3D               extent;
uint32_t                 mipLevels;
uint32_t                 arrayLayers;
VkSampleCountFlagBits    samples;
VkImageTiling            tiling;
VkImageUsageFlags        usage;
VkSharingMode            sharingMode;
uint32_t                 queueFamilyIndexCount;
const uint32_t*          pQueueFamilyIndices;
VkImageLayout            initialLayout;
} VkImageCreateInfo;

• sType is the type of this structure.
• pNext is NULL or a pointer to an extension-specific structure.
• flags is a bitfield describing additional parameters of the image. See VkImageCreateFlagBits below for a description of the supported bits.
• imageType is the basic dimensionality of the image, and must be one of the values

typedef enum VkImageType {
VK_IMAGE_TYPE_1D = 0,
VK_IMAGE_TYPE_2D = 1,
VK_IMAGE_TYPE_3D = 2,
} VkImageType;

specifying one-, two-, or three-dimensionality, respectively. Layers in array textures do not count as a dimension for the purposes of the image type.

• format is a VkFormat describing the format and type of the data elements that will be contained in the image.
• extent is a VkExtent3D describing the number of data elements in each dimension of the base level.
• mipLevels describes the number of levels of detail available for minified sampling of the image.
• arrayLayers is the number of layers in the image.
• samples is the number of sub-data element samples in the image as defined in VkSampleCountFlagBits. See Multisampling.
• tiling is the tiling arrangement of the data elements in memory, and must have one of the values:

typedef enum VkImageTiling {
VK_IMAGE_TILING_OPTIMAL = 0,
VK_IMAGE_TILING_LINEAR = 1,
} VkImageTiling;

VK_IMAGE_TILING_OPTIMAL specifies optimal tiling (texels are laid out in an implementation-dependent arrangement, for more optimal memory access), and VK_IMAGE_TILING_LINEAR specifies linear tiling (texels are laid out in memory in row-major order, possibly with some padding on each row).

• usage is a bitfield describing the intended usage of the image. See VkImageUsageFlagBits below for a description of the supported bits.
• sharingMode is the sharing mode of the image when it will be accessed by multiple queue families, and must be one of the values described for VkSharingMode in the Resource Sharing section below.
• queueFamilyIndexCount is the number of entries in the pQueueFamilyIndices array.
• pQueueFamilyIndices is a list of queue families that will access this image (ignored if sharingMode is not VK_SHARING_MODE_CONCURRENT).
• initialLayout selects the initial VkImageLayout state of all image subresources of the image. See Image Layouts. initialLayout must be VK_IMAGE_LAYOUT_UNDEFINED or VK_IMAGE_LAYOUT_PREINITIALIZED.

Valid limits for the image extent, mipLevels, arrayLayers and samples members are queried with the vkGetPhysicalDeviceImageFormatProperties command.

Images created with tiling equal to VK_IMAGE_TILING_LINEAR have further restrictions on their limits and capabilities compared to images created with tiling equal to VK_IMAGE_TILING_OPTIMAL. Creation of images with tiling VK_IMAGE_TILING_LINEAR may not be supported unless other parameters meet all of the constraints:

• imageType is VK_IMAGE_TYPE_2D
• format is not a depth/stencil format
• mipLevels is 1
• arrayLayers is 1
• samples is VK_SAMPLE_COUNT_1_BIT
• usage only includes VK_IMAGE_USAGE_TRANSFER_SRC_BIT and/or VK_IMAGE_USAGE_TRANSFER_DST_BIT

Implementations may support additional limits and capabilities beyond those listed above. To determine the specific capabilities of an implementation, query the valid usage bits by calling vkGetPhysicalDeviceFormatProperties and the valid limits for mipLevels and arrayLayers by calling vkGetPhysicalDeviceImageFormatProperties.

Bits which may be set in usage are:

typedef enum VkImageUsageFlagBits {
VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 0x00000001,
VK_IMAGE_USAGE_TRANSFER_DST_BIT = 0x00000002,
VK_IMAGE_USAGE_SAMPLED_BIT = 0x00000004,
VK_IMAGE_USAGE_STORAGE_BIT = 0x00000008,
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020,
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040,
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080,
} VkImageUsageFlagBits;

These bitfields have the following meanings:

• VK_IMAGE_USAGE_TRANSFER_SRC_BIT indicates that the image can be used as the source of a transfer command.
• VK_IMAGE_USAGE_TRANSFER_DST_BIT indicates that the image can be used as the destination of a transfer command.
• VK_IMAGE_USAGE_SAMPLED_BIT indicates that the image can be used to create a VkImageView suitable for occupying a VkDescriptorSet slot either of type VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE or VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, and be sampled by a shader.
• VK_IMAGE_USAGE_STORAGE_BIT indicates that the image can be used to create a VkImageView suitable for occupying a VkDescriptorSet slot of type VK_DESCRIPTOR_TYPE_STORAGE_IMAGE.
• VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT indicates that the image can be used to create a VkImageView suitable for use as a color or resolve attachment in a VkFramebuffer.
• VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT indicates that the image can be used to create a VkImageView suitable for use as a depth/stencil attachment in a VkFramebuffer.
• VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT indicates that the memory bound to this image will have been allocated with the VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT (see Chapter 10, Memory Allocation for more detail). If this is set, then bits other than VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, and VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT must not be set.
• VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT indicates that the image can be used to create a VkImageView suitable for occupying VkDescriptorSet slot of type VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; be read from a shader as an input attachment; and be used as an input attachment in a framebuffer.

Bits which may be set in flags are:

typedef enum VkImageCreateFlagBits {
VK_IMAGE_CREATE_SPARSE_BINDING_BIT = 0x00000001,
VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002,
VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008,
VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010,
} VkImageCreateFlagBits;

These bitfields have the following meanings:

• VK_IMAGE_CREATE_SPARSE_BINDING_BIT indicates that the image will be backed using sparse memory binding.
• VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT indicates that the image can be partially backed using sparse memory binding. Images created with this flag must also be created with the VK_IMAGE_CREATE_SPARSE_BINDING_BIT flag.
• VK_IMAGE_CREATE_SPARSE_ALIASED_BIT indicates that the image will be backed using sparse memory binding with memory ranges that might also simultaneously be backing another image (or another portion of the same image). Images created with this flag must also be created with the VK_IMAGE_CREATE_SPARSE_BINDING_BIT flag

If any of these three bits are set, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT must not also be set.

See Sparse Resource Features and Sparse Physical Device Features for more details.

• VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT indicates that the image can be used to create a VkImageView with a different format from the image.
• VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT indicates that the image can be used to create a VkImageView of type VK_IMAGE_VIEW_TYPE_CUBE or VK_IMAGE_VIEW_TYPE_CUBE_ARRAY.

To query the host access layout of an image subresource, for an image created with linear tiling, call:

void vkGetImageSubresourceLayout(
VkDevice                                    device,
VkImage                                     image,
const VkImageSubresource*                   pSubresource,
VkSubresourceLayout*                        pLayout);

• device is the logical device that owns the image.
• image is the image whose layout is being queried.
• pSubresource is a pointer to a VkImageSubresource structure selecting a specific image for the image subresource.
• pLayout points to a VkSubresourceLayout structure in which the layout is returned.

vkGetImageSubresourceLayout is invariant for the lifetime of a single image.

The VkImageSubresource structure is defined as:

typedef struct VkImageSubresource {
uint32_t              mipLevel;
uint32_t              arrayLayer;
} VkImageSubresource;

• aspectMask is a VkImageAspectFlags selecting the image aspect.
• mipLevel selects the mipmap level.
• arrayLayer selects the array layer.

Information about the layout of the image subresource is returned in a VkSubresourceLayout structure:

typedef struct VkSubresourceLayout {
VkDeviceSize    offset;
VkDeviceSize    size;
VkDeviceSize    rowPitch;
VkDeviceSize    arrayPitch;
VkDeviceSize    depthPitch;
} VkSubresourceLayout;

• offset is the byte offset from the start of the image where the image subresource begins.
• size is the size in bytes of the image subresource. size includes any extra memory that is required based on rowPitch.
• rowPitch describes the number of bytes between each row of texels in an image.
• arrayPitch describes the number of bytes between each array layer of an image.
• depthPitch describes the number of bytes between each slice of 3D image.

For images created with linear tiling, rowPitch, arrayPitch and depthPitch describe the layout of the image subresource in linear memory. For uncompressed formats, rowPitch is the number of bytes between texels with the same x coordinate in adjacent rows (y coordinates differ by one). arrayPitch is the number of bytes between texels with the same x and y coordinate in adjacent array layers of the image (array layer values differ by one). depthPitch is the number of bytes between texels with the same x and y coordinate in adjacent slices of a 3D image (z coordinates differ by one). Expressed as an addressing formula, the starting byte of a texel in the image subresource has address:

// (x,y,z,layer) are in texel coordinates
address(x,y,z,layer) = layer*arrayPitch + z*depthPitch + y*rowPitch + x*texelSize + offset

For compressed formats, the rowPitch is the number of bytes between compressed texel blocks in adjacent rows. arrayPitch is the number of bytes between compressed texel blocks in adjacent array layers. depthPitch is the number of bytes between compressed texel blocks in adjacent slices of a 3D image.

// (x,y,z,layer) are in compressed texel block coordinates
address(x,y,z,layer) = layer*arrayPitch + z*depthPitch + y*rowPitch + x*compressedTexelBlockByteSize + offset;

arrayPitch is undefined for images that were not created as arrays. depthPitch is defined only for 3D images.

For color formats, the aspectMask member of VkImageSubresource must be VK_IMAGE_ASPECT_COLOR_BIT. For depth/stencil formats, aspectMask must be either VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT. On implementations that store depth and stencil aspects separately, querying each of these image subresource layouts will return a different offset and size representing the region of memory used for that aspect. On implementations that store depth and stencil aspects interleaved, the same offset and size are returned and represent the interleaved memory allocation.

To destroy an image, call:

void vkDestroyImage(
VkDevice                                    device,
VkImage                                     image,
const VkAllocationCallbacks*                pAllocator);

• device is the logical device that destroys the image.
• image is the image to destroy.
• pAllocator controls host memory allocation as described in the Memory Allocation chapter.