Chapter 6. Allocating Image Resources and Building a Swapchain with WSI

In the previous chapter, we covered concepts related to memory management and command buffers. We learned about host and device memory and ways to allocate in the Vulkan API. We also covered command buffers; we implemented command buffer recording API calls and submitted them to queues for processing.

In this chapter, we will make use of our knowledge of command buffers and memory allocation to implement a swapchain and depth image. A swapchain provides the mechanism by which we can render drawing primitives to swapchain color images, which is then passed on to the presentation layer in order to display the primitives in the window. Images are a prerequisite of swap buffer creation; therefore, this chapter will help you gain in-depth knowledge of image resources and their uses in the Vulkan application.

We will cover the following topics:

  • Getting started with image resources
  • Understanding an image resource
  • Memory allocation and binding an image resource
  • Introducing swapchains
  • Creating a depth image
  • Summarizing the application flow

Getting started with image resources

A Vulkan resource is simply a representation of a memory view that contains data. Vulkan primarily has two types of resource: buffers and images. In this chapter, we will only discuss the concept of an image resource; this will be used to implement the swapchain. For more information on the buffer resource type, refer to Chapter 7, Buffer Resource, Render Pass, Framebuffer, and Shaders with SPIR-V. In order to get an overview of this, you may want to revisit the Resource objects - managing images and buffers section in Chapter 2, Your First Vulkan Pseudo Program.

Vulkan images represent contiguous texture data in 1D/2D/3D form. These images are primarily used as either an attachment or texture:

  • Attachment: The image is attached to the pipeline for the framebuffer's color or depth attachment and can also be used as an auxiliary surface for multipass processing purposes
  • Texture: The image is used as a descriptor interface and shared at the shader stage (fragment shader) in the form of samplers

Note

If you come from an OpenGL background, note that the use of images in Vulkan is entirely different from its counterpart in OpenGL. In Vulkan, the image is created by specifying a number of bitwise fields indicating the kind of image usage, such as color attachment, depth/stencil attachment, a sampled image in a shader, image load/store, and so on. In addition, you need to specify the tiling information (linear or optimal) for the image. This specifies the tiling or swizzling layout for the image data in memory.

The notion of texture in Vulkan is primarily interpreted with images, image layouts, and image views:

  • Image: An image represents the texture object in Vulkan. This contains metadata that is utilized for computing memory requirements. The gathered memory requirements are helpful during memory allocation. An image indicates other, and numerous types of information, such as the format, size, and type (sparse map, cube map, and so on). A single image may contain sub-resources, such as multiple images, based on the mipmap level or array layers. Each image or image sub-resource is specified with an image layout.
  • Image layout: An image layout is an implementation-specific way to store image texture information in a grid coordinate representation in the image memory. The image stored in image memory is very implementation-specific; each image has a specific usage, for example, color attachment, a sampled image in a shader, image load/store, or sparse textures for large images. For these special purposes, the implementation provides image layouts that are specialized in image memory usage to offer optimal performance.

Note

Each image layout is special. Each may offer only certain features. For example, an image specified with the VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL image layout can be used as a color image attachment for optimal performance; however, it cannot be used for transfer purposes.

  • Image view: Images cannot be used directly for reading and writing purposes by API calls or pipeline shaders; instead, image views are used. It not only acts like an interface to the image object, but it also provides the metadata that is used to represent a continuous range of image sub-resources.

Image creation overview

In this section, we will provide you with a quick introduction to the image creation process in a step-by-step manner. This will be helpful in getting an overview of the image, image views, and the associated memory allocations. This section is immediately followed by two other sections that will cover images (Understanding an image resource) and their memory allocation (Memory allocation and binding image resources) along with a detailed description of the corresponding APIs.

The following are step-by-step instructions on how to create an image resource using Vulkan APIs:

  1. First, create the image object:
    • Create an image object (VkImage) using the vkCreateImage() API. This API intakes an array of the VkImageCreateInfo structure, which specifies important image characteristics that are helpful in creating one or more image objects. At this time, the image object has no physical allocation on the device; however, it has logical memory information that will be used to allocate memory in the next step. This memory information comes from the VkImageCreateInfo object, which contains the format, image size, creation flags, and so on.

  2. Then, allocate image memory:
    • Getting the memory requirements: Before we allocate the required chunk of image memory, we need to calculate the appropriate size of the memory we want to allocate. This is done using the vkGetImageMemoryRequirements() API. It automates the process of calculating the appropriate size of the image based on the image properties. It intakes the VkCreateImageInfo object that we described in the previous step.
    • Determining the memory type: Next, get the appropriate memory type from the available memory types. Once the type is made available, look for a type that matches the user properties.
    • Allocating device memory: Allocate the device memory (VkDeviceMemory) with the vkAllocateMemory() API.
    • Binding the allocated memory: Bind the allocated device memory (VkDeviceMemory) to the image object (VkImage) using the vkBindImageMemory() API.

  3. Set the image layout:
    • Set the correct image layout as per application requirements; do this using pipeline image memory barriers with vkCmdPipelineBarrier().

  4. Create the image views:
    • Images can only be accessed via image views. This is the final step where we create an image view using vkCreateImageView(). The image can now be used by either API calls or pipeline shaders.

Image creation overview

..................Content has been hidden....................

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