Image Views
For this chapter, we'll be back in our initSwapchain method. We'll start with a for loop where we will be setting image layouts and creating image views. It will look like this:
for (uint32_t i = 0; i < imageCount; i++) {
  // We'll be filling this out
}
Image View Create Information
In Vulkan, we don't directly access images from shaders for reading and writing. Instead, we make use of image views. We can use VkImageViewCreateInfo to specify certain traits for each image view we want to create. Essentially, image views wrap up image objects and can provide additional metadata.
Definition for VkImageViewCreateInfo:
typedef struct VkImageViewCreateInfo {
  VkStructureType            sType;
  const void*                pNext;
  VkImageViewCreateFlags     flags;
  VkImage                    image;
  VkImageViewType            viewType;
  VkFormat                   format;
  VkComponentMapping         components;
  VkImageSubresourceRange    subresourceRange;
} VkImageViewCreateInfo;
Documentation for VkImageViewCreateInfo:
- sTypeis the type of this structure.
- pNextis- NULLor a pointer to an extension-specific structure.
- flagsis reserved for future use.
- imageis a- VkImageon which the view will be created.
- viewTypeis the type of the image view.
- formatis a- VkFormatdescribing the format and type used to interpret data elements in the image.
- componentsspecifies a remapping of color components (or of depth or stencil components after they have been converted into color components).
- subresourceRangeselects the set of mipmap levels and array layers to be accessible to the view.
Usage for VkImageViewCreateInfo:
VkImageViewCreateInfo imageCreateInfo = {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
imageCreateInfo.pNext = NULL;
imageCreateInfo.format = colorFormat;
imageCreateInfo.components = {}; // We'll get to this in a second!
imageCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageCreateInfo.subresourceRange.baseMipLevel = 0;
imageCreateInfo.subresourceRange.levelCount = 1;
imageCreateInfo.subresourceRange.baseArrayLayer = 0;
imageCreateInfo.subresourceRange.layerCount = 1;
imageCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
imageCreateInfo.flags = 0;
Notice I did not finish the components line. You can see this section for more information on component mapping. But, what we're doing is telling Vulkan how to map image components to vector components output by our shaders. We'll simply tell Vulkan we want our (R, G, B, A) images to map to a vector in the form <R, G, B, A>. We can do that like so:
imageCreateInfo.components = {
    VK_COMPONENT_SWIZZLE_R,
    VK_COMPONENT_SWIZZLE_G,
    VK_COMPONENT_SWIZZLE_B,
    VK_COMPONENT_SWIZZLE_A};
Unless you know what you're doing, just use RGBA values. Before we create the image, let's make sure we store it and call the setImageLayout method with it. We'll also finish filling out the imageCreateInfo:
buffers[i].image = images[i];
setImageLayout(cmdBuffer, buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT,
               VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
imageCreateInfo.image = buffers[i].image;
Creating an Image View
To create our image view, we simply call vkCreateImageView.
Definition for vkCreateImageView:
VkResult vkCreateImageView(
  VkDevice                     device,
  const VkImageViewCreateInfo* pCreateInfo,
  const VkAllocationCallbacks* pAllocator,
  VkImageView*                 pView);
  device
Documentation for vkCreateImageView:
- deviceis the logical device that creates the image view.
- pCreateInfois a pointer to an instance of the- VkImageViewCreateInfostructure containing parameters to be used to create the image view.
- pAllocatorcontrols host memory allocation.
- pViewpoints to a- VkImageViewhandle in which the resulting image view object is returned.
Usage for vkCreateImageView:
result =
    vkCreateImageView(device, &imageCreateInfo, NULL, &buffers[i].view);
assert(result == VK_SUCCESS);
Framebuffer Create Information
We're going to be creating framebuffers for every image in the swapchain. Thus, we'll continue writing the body of our for loop. Like most types in Vulkan, we'll need to create an info structure before we can create a framebuffer. This is called VkFramebufferCreateInfo.
Definition for VkFramebufferCreateInfo:
typedef struct VkFramebufferCreateInfo {
  VkStructureType             sType;
  const void*                 pNext;
  VkFramebufferCreateFlags    flags;
  VkRenderPass                renderPass;
  uint32_t                    attachmentCount;
  const VkImageView*          pAttachments;
  uint32_t                    width;
  uint32_t                    height;
  uint32_t                    layers;
} VkFramebufferCreateInfo;
Documentation for VkFramebufferCreateInfo:
- sTypeis the type of this structure.
- pNextis- NULLor a pointer to an extension-specific structure.
- flagsis reserved for future use.
- renderPassis a render pass that defines what render passes the framebuffer will be compatible with.
- attachmentCountis the number of attachments.
- pAttachmentsis an array of- VkImageViewhandles, each of which will be used as the corresponding attachment in a render pass instance. width, height and layers define the dimensions of the framebuffer.
Usage for VkFramebufferCreateInfo:
We'll set the width and height to that of the swapchainExtent from earlier.
VkFramebufferCreateInfo fbCreateInfo = {};
fbCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
fbCreateInfo.attachmentCount = 1;
fbCreateInfo.pAttachments = &buffers[i].view;
fbCreateInfo.width = swapchainExtent.width;
fbCreateInfo.height = swapchainExtent.height;
fbCreateInfo.layers = 1;
Creating a Framebuffer
Now we can create each framebuffer. We'll call vkCreateFramebuffer.
Definition for vkCreateFramebuffer:
VkResult vkCreateFramebuffer(
  VkDevice                       device,
  const VkFramebufferCreateInfo* pCreateInfo,
  const VkAllocationCallbacks*   pAllocator,
  VkFramebuffer*                 pFramebuffer);
Documentation for vkCreateFramebuffer:
- deviceis the logical device that creates the framebuffer.
- pCreateInfopoints to a- VkFramebufferCreateInfostructure which describes additional information about framebuffer creation.
- pAllocatorcontrols host memory allocation.
- pFramebufferpoints to a- VkFramebufferhandle in which the resulting framebuffer object is returned.
Usage for vkCreateFramebuffer:
result = vkCreateFramebuffer(device, &fbCreateInfo, NULL,
                             &buffers[i].frameBuffer);
assert(result == VK_SUCCESS);
That's all we'll need for our initSwapchain method! Now it's time for acquiring the next image in the swapchain and presenting images!