Chapter 9. Drawing Objects

In the last two chapters, we implemented the Render Pass instance and displayed swapchain images with specified background colors. In the previous chapter, we put various pipeline states together along with Render Pass in the graphics pipeline. In this chapter, we will put all previous implementations together to build the first Hello World! program in Vulkan and display our first rendering object on the display output.

This chapter thoroughly covers the process of drawing objects in Vulkan; it comprises recording and executing the drawing object's command buffers. The recording associates the Render Pass, framebuffer, and the pipeline together with the viewport and geometry data. Command buffer execution involves submitting the command buffer in the device queue and presenting the drawn swapchain image onto the presentation engine. Toward the end of this chapter, we will discuss various synchronization primitives available in the Vulkan API.

In this chapter, we will cover the following topics:

  • Overview of the drawing process in Vulkan
  • Preparing the drawing object
  • Rendering the drawing object
  • Rendering an indexed geometry
  • Understanding synchronization primitives in Vulkan
  • Resizing the display window

Overview of the drawing process in Vulkan

Implementing a drawing object in Vulkan is simple; it consists of two phases: preparation, or building the drawing object, and rendering it. The former phase produces the command buffer and records the drawing commands. In the latter phase, the command buffer executes these drawing commands to render the object. Let's take a look at these phases in detail:

  1. Preparing the drawing object: This phase produces the command buffers required to draw objects:
    • Command buffer creation: For each swapchain color image, create a corresponding command buffer object. For example, if the swapchain is a double buffer, then it will contain two color images. As a result, we should be creating two command buffers that correspond to each image.
    • Command buffer recording: For the command buffer created, record the Render Pass instance commands single subpass at ; refer to the following steps:
      • Associate the created Render Pass object and framebuffer with the required dimensions of the presentation's render area.
      • Specify the scalar values for clearing the background color and depth image. We implemented this step in Chapter 7, Buffer Resource, Render Pass, Framebuffer, and Shaders with SPIR-V. For more information, please refer to the Clearing the background color section.
      • Bind the graphics pipeline object.
      • Bind the resources used by the pipeline, including vertex buffers and descriptor sets.
      • Define the viewport and scissoring region.
      • Draw the object.

  2. Rendering the drawing object: Here, the created command buffers in the preparation phase are reused and executed again and again to render the drawing object:
    • Get the swapchain image that is available to perform rendering on it.
    • Submit the command buffer to render the object.
    • Display the rendered drawing image on the presentation engine.

The preparation and rendering of the drawable object are implemented through the prepare() and render() functions of the VulkanDrawable class.

Walking through the header declaration

In this section, we will take a look at the header file declaration for VulkanDrawable. Please follow through the inline comments to understand the functionality and purpose of each function and variable. As we proceed through the chapter, we will implement these functions and discuss them in detail. The following are the new member variables and functions added:

class VulkanDrawable 
{ 
  public: 
  // Prepares the drawing object before rendering,

  // allocate, create, record command buffer 
  void prepare(); 
 
  // Renders the drawing object 
  void render(); 
 
  // Initialize the viewport parameters here 
  void initViewports(VkCommandBuffer* cmd); 
 
  // Initialize the scissor parameters here 
  void initScissors(VkCommandBuffer* cmd); 
 
  // Destroy the drawing command buffer object 
  void destroyCommandBuffer(); 
  private: 
  // Command buffer for drawing 
  std::vector<VkCommandBuffer> vecCmdDraw; 
 
  // Prepares render pass instance 
  void recordCommandBuffer(int currentImage, 
  VkCommandBuffer* cmdDraw); 
 
  // Viewport and Scissor variables 
  VkViewport viewport; 
  VkRect2D scissor; 
  VkSemaphore presentCompleteSemaphore;
  VkSemaphore drawingCompleteSemaphore;
}; 

The prepare() function creates the command buffer objects, which are used in the render() function to draw the object. The prepare() function allocates the memory for the command buffer (vecCmdDraw) from the command pool (VulkanRenderer::cmdPool) and creates the command buffer object. The command buffer commands are recorded inside the recordCommandBuffer() function; this creates the Render Pass instance and other important jobs, such as associating the graphics pipeline with the drawing object and specifying the viewport and scissoring management through initViewport() and initScissor().

The render() function uses the prepared recorded command buffer and renders the drawing on the available swapchain color image. Once the drawing is finished on the swapchain's color image, then it is given to the presentation engine for display purposes.

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

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