drawFrame

Executes the recorded command buffers. The recorded operations will end up rendering and presenting the frame to the surface

This is where the recorded command buffers are executed. The recorded operations will end up rendering and presenting the frame to the surface.

Wait for the fence to be signalled before starting to render the current frame, then reset it so it can be reused.

 	vkWaitForFences(appManager.device, 1, &appManager.frameFences[frameId], true, FENCE_TIMEOUT)
 
 	vkResetFences(appManager.device, 1, &appManager.frameFences[frameId]);
 

currentBuffer will be used to point to the correct frame/command buffer/uniform buffer data.

It is going to be the general index of the data being worked on.

 	uint32_t currentBuffer = 0;
 	VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
 

Acquire and get the index of the next available swapchain image.

 	vkAcquireNextImageKHR(appManager.device, appManager.swapchain, std::numeric_limits<uint64_t>::max(), appManager.acquireSemaphore[frameId], VK_NULL_HANDLE, &currentBuffer);
 

Use a helper function with the current frame index to calculate the transformation matrix and write it into the correct slice of the uniform buffer.

 	applyRotation(currentBuffer);
 

Submit the command buffer to the queue to start rendering.

The command buffer is submitted to the graphics queue which was created earlier.

Notice the wait (acquire) and signal (present) semaphores, and the fence.

 	VkSubmitInfo submitInfo = {};
 	submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
 	submitInfo.pNext = nullptr;
 	submitInfo.pWaitDstStageMask = &pipe_stage_flags;
 	submitInfo.waitSemaphoreCount = 1;
 	submitInfo.pWaitSemaphores = &appManager.acquireSemaphore[frameId];
 	submitInfo.signalSemaphoreCount = 1;
 	submitInfo.pSignalSemaphores = &appManager.presentSemaphores[frameId];
 	submitInfo.commandBufferCount = 1;
 	submitInfo.pCommandBuffers = &appManager.commandBuffers[currentBuffer];
 
 	vkQueueSubmit(appManager.graphicQueue, 1, &submitInfo, appManager.frameFences[frameId])
 

Queue the rendered image for presentation to the surface.

The currentBuffer is again used to select the correct swapchain images to present. A wait semaphore is also set here which will be signalled when the command buffer has finished execution.

 	VkPresentInfoKHR presentInfo;
 	presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
 	presentInfo.pNext = nullptr;
 	presentInfo.swapchainCount = 1;
 	presentInfo.pSwapchains = &appManager.swapchain;
 	presentInfo.pImageIndices = &currentBuffer;
 	presentInfo.pWaitSemaphores = &appManager.presentSemaphores[frameId];
 	presentInfo.waitSemaphoreCount = 1;
 	presentInfo.pResults = nullptr;
 
 	vkQueuePresentKHR(appManager.presentQueue, &presentInfo)
 

Update the frameId to get the next suitable one.

 	frameId = (frameId + 1) % appManager.swapChainImages.size();