Understanding image resources

This section will cover the Vulkan APIs used to create an image resource. Here, we'll look into the concept of a data image, image view, and image layout in detail.

Creating images

An image resource in Vulkan is represented using the VkImage object. This object supports a multidimensional image up to three-dimensional data arrays. Images are created using the vkCreateImage() API. Here's the syntax to do this:

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

The following table describes the various fields of VkCommandPoolCreateInfo:

Parameters

Description

device

This refers to the logical device responsible for creating an image.

pCreateInfo

This refers to a VkImageCreateInfo pointer.

pAllocator

This controls the host memory allocation process.

pImage

This returns the VkImage pointer after it's created.

The vkCreateImage() intakes VkImageCreateInfo as a second parameter, this control structure is defined here:

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; 

The following table describes the various fields of VkImageCreateInfo:

Parameters

Description

sType

This is the type information of this control structure. It must be specified as VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO.

pNext

This could be a valid pointer to an extension-specific structure or NULL.

flags

This refers to the VkImageCreateFlagBits bit field flags. More information on this will be provided later in this section.

imageType

This specifies the 1D/2D/3D dimensionality of the image using the VkImageType enum. It must be one of these: VK_IMAGE_TYPE_1D, VK_IMAGE_TYPE_2D, or VK_IMAGE_TYPE_3D.

format

This refers to the image format specified in the VkFormat type. It describes the format and type of the data elements that will be contained in the image.

extent

This describes the number of elements in each dimension of the base level.

mipLevels

This refers to the different levels of detail available in the minified sampling image.

arrayLayers

This specifies the number of layers in the image.

samples

This specifies the number of subdata element samples in the image, as defined in VkSampleCountFlagBits.

tilings

This specifies the tiling information of the image in the memory. It should be of the type VkImageTiling and must be either one of these two enum values: VK_IMAGE_TILING_OPTIMAL or VK_IMAGE_TILING_LINEAR.

usage

This refers to VkImageUsageFlagBits specifying the bit field that describes the intended usage of the image. More information on this will be provided later in this section.

sharingMode

This specifies the sharing mode of the image when it will be accessed by multiple queue families. This must be one of these values: VK_SHARING_MODE_EXCLUSIVE or VK_SHARING_MODE_CONCURRENT from the VkSharingMode enum.

queueFamilyIndexCount

This represents the number of entries in the queueFamilyIndices array.

queueFamilyIndices

This is an array of queue families that will access the image. The sharingMode must be VK_SHARING_MODE_CONCURRENT; otherwise, ignore it.

initialLayout

This defines the initial VkImageLayout state of all the sub-resources of the images. This must be either VK_IMAGE_LAYOUT_UNDEFINED or VK_IMAGE_LAYOUT_PREINITIALIZED. For more information on image layouts, refer to the Understanding the image layouts section of this chapter.

The image's usage flag of the VkImageCreateInfo control structure is described using the VkImageUsageFlagBits enum flag. The following is the syntax followed by a description of each field type of this enum:

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; 

Let's look at these bitwise fields in detail to understand what they mean:

Enum type

Description

VK_IMAGE_USAGE_TRANSFER_SRC_BIT

The image is used by the transfer command's (the copy command) source.

VK_IMAGE_USAGE_TRANSFER_DST_BIT

The image is used by the transfer command's (the copy command) destination.

VK_IMAGE_USAGE_SAMPLED_BIT

This image type is used as a sampler at the shading stage through the image view type, where the associated descriptor set slot (VkDescriptorSet) type could be either VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE or VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER.

The sampled image in the shader is used for address calculations, controlling the filtering behavior, and other attributes.

VK_IMAGE_USAGE_STORAGE_BIT

Use this image type for load, store, and atomic operations on the image memory. The image view is associated with the descriptor type slot of the type VK_DESCRIPTOR_TYPE_STORAGE_IMAGE.

VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT

The image view created from this type of image resource is appropriate for a color attachment or the resolve attachment associated with the frame buffer object (VkFrameBuffer).

VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT

The image view created from this type of image resource is appropriate for a depth/stencil attachment or the resolve attachment associated with the frame buffer object (VkFrameBuffer).

VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT

The image type represented by this flag is allocated lazily. The memory type for this must be specified as VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT. Note that if this flag is specified, then VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, and VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT must not be used.

VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT

The image view created from this type of image resource is appropriate for an input attachment in the shader stage and in the frame buffer. This image view must be associated with the descriptor set slot (VkDescriptorSet) of the type VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT.

Note

The memory allocated with the VK_MEMORY_PROPERTY_LAZILY_-ALLOCATED_BIT bit flag is not allocated upfront as per the requested size, but it may be allocated in a monotonic fashion where memory gradually increases with application demand.

The flag field in the VkImageCreateInfo enum hints the underlying application how it manages various image resources, such as memory, format, and attributes, using the VkImageCreateFlagBits enum. The following is the syntax of each type:

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, 
    VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM       = 0x7FFFFFFF 
} VkImageCreateFlagBits; 
typedef VkFlags VkImageCreateFlags; 

Now let's understand the flag definitions:

Flags

Description

VK_IMAGE_CREATE_SPARSE_BINDING_BIT

The image is fully stored using sparse memory binding.

VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT

Here the images can be stored partially using sparse memory binding. In order to use this field, the image must have the VK_IMAGE_CREATE_SPARSE_BINDING_BIT flag.

VK_IMAGE_CREATE_SPARSE_ALIASED_BIT

In this type of flag, the image is stored in sparse memory; it can also hold multiple portions of the same image in the same memory regions. The image must be created using the VK_IMAGE_CREATE_SPARSE_BINDING_BIT flag.

VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT

This format is useful in cases where the image view (VkImageView) format is different from the created image object format itself (VkImage).

VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT

This format is used for cube mapping. In this case, VkImageView must be of the type VK_IMAGE_VIEW_TYPE_CUBE or VK_IMAGE_VIEW_TYPE_CUBE_ARRAY.

Destroying the created images

When the image is no longer required, it can be destroyed using vkDestroyImage(). Here's the syntax to do this:

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

This API accepts three parameters, which are described in the following table:

Parameters

Description

device

This is the logical device that destroys image.

image

This is the VkImage object that needs to be destroyed.

pAllocator

This controls the host memory deallocation process. Refer to the Host memory section in Chapter 5, Command Buffer and Memory Management in Vulkan.

Understanding image layouts

Let's take a look at the various image layouts available in the Vulkan specification. They are represented by the VkImageLayout enum values, as described in the following list:

  • VK_IMAGE_LAYOUT_UNDEFINED: This layout does not support device access. This is most suitable for either intialLayout or oldLayout in an image transition. The transitioning of this layout does not provide any guarantee of preserving the memory data it holds.
  • VK_IMAGE_LAYOUT_GENERAL: This layout supports all types of device access.
  • VK_IMAGE_LAYOUT_PREINITIALIZED: This layout also does not support device access and is most suitable for either intialLayout or oldLayout in an image transition. The contents held by the layout memory are preserved while transitioning. This type of layout is useful in cases where the data is readily available at the initialization time. This way, the data can be directly stored in device memory immediately, without requiring an extra step to execute the layout transition.
  • VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: This layout is very suitable for color images. Therefore, it must only be used with the color and resolved attachment of VkFrameBuffer. In order to use this layout, the image must have the usage bit set as VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT.

Note

Image sub-resources do not have the usage bits specified individually--they are specified for the whole image only.

  • VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: This layout must only be used for the depth/stencil attachment of VkFrameBuffer. In order to use this layout, the image must have the usage bit set as VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT.
  • VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: This is similar to VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, except that it's used as a read-only VkFrameBuffer attachment or a read-only image in a shader, where it must be read as a sampled image, combined image/sampler, and/or input attachment. The image must be created with the usage bit set as VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT.
  • VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: This must be used as a read-only shader image, for example, a sampled image, combined image/sampler, and/or input attachment. The image sub-resource must be created either with the usage bit set as VK_IMAGE_USAGE_SAMPLED_BIT or VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT.
  • VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: This must be used as the source image of a transfer command with a transfer pipeline, and its usage is valid only if the image sub-resource has the usage bit set as VK_IMAGE_USAGE_TRANSFER_SRC_BIT.
  • VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: This must be used as the destination image of a transfer command with a transfer pipeline, and its usage is valid only if the image sub-resource has the usage bit set as VK_IMAGE_USAGE_TRANSFER_DST_BIT.

Creating an image view

An image view is created using vkCreateImageView(). Here's the syntax of this:

VkResult vkCreateImageView( 
    VkDevice                      device, 
    const VkImageViewCreateInfo*  pCreateInfo, 
    const VkAllocationCallbacks*  pAllocator, 
    VkImageView*                  pView); 

The following table describes the various fields of VkCommandPoolCreateInfo:

Parameters

Description

device

This is the handle of the logical device that creates the image view.

pCreateInfo

This is the pointer to VkCreateImageViewInfo; it controls the creation of VkImageView.

pAllocator

This controls the host memory allocation process. For more information, refer to the Host memory section in Chapter 5, Command Buffer and Memory Management in Vulkan.

pView

This returns the handle of the created VkImageView object.

The VkCreateImageViewInfo data structure contains view-specific attributes that are consumed by the vkCreateImageView() API to create the image view. The following is the syntax of each field:

typedef struct VkImageViewCreateInfo { 
    VkStructureType            sType; 
    const void*                pNext; 
    VkImageViewCreateFlags     flags; 
    VkImage                    image; 
    VkImageViewType            viewType; 
    VkFormat                   format; 
    VkComponentMapping         components; 
    VkImageSubresourceRange    subresourceRange; 
} VkImageViewCreateInfo; 

The following table describes the various fields of VkImageViewCreateInfo:

Parameters

Description

sType

This is the type information of the structure; it must be VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO.

pNext

This is an extension-specific structure. This field could be NULL as well.

flags

This field is NULL; it is reserved for future use.

image

This is the handle of VkImage.

viewType

This indicates the image view type using the enum VkImageViewType. It must be either one of these flag values: VK_IMAGE_VIEW_TYPE_1D, VK_IMAGE_VIEW_TYPE_2D,

VK_IMAGE_VIEW_TYPE_3D, VK_IMAGE_VIEW_TYPE_CUBE,

VK_IMAGE_VIEW_TYPE_1D_ARRAY, VK_IMAGE_VIEW_TYPE-_2D_ARRAY, or VK_IMAGE_VIEW_TYPE_CUBE_ARRAY.

format

This specifies the format (VkFormat) of the image.

components

This is used for remapping the color/depth/stencil after it has been converted into color components.

subresourceRange

This is used for selecting a range of mipmap levels and array layers, which are accessible through the view.

Destroying the image view

An image view is destroyed using the vkDestroyImageView() API. This API intakes three parameters. The first parameter (device) specifies the logical device that is responsible for destroying the image view (imageView), which is indicated by the second parameter. The last parameter pAllocator controls the host memory allocation process. Here's the syntax of this:

void vkDestroyImageView(VkDevice device, 
                        VkImageView   imageView, 
                        VkAllocationCallbacks* pAllocator); 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.255.87