recordCommandBuffer

Records rendering commands to the command buffers

This function will record a set of commands in the command buffers which will render a basic triangle on screen.

State the clear values for rendering.

This is the colour value that the framebuffer is cleared to at the start of the render pass.

The framebuffer is cleared because, during render pass creation, the loadOp parameter was set to VK_LOAD_OP_CLEAR. Remember that this is crucial as it can reduce system memory bandwidth and reduce power consumption, particularly on PowerVR platforms.

 	VkClearValue clearColor = { 0.00f, 0.70f, 0.67f, 1.0f };
 	

This is a constant offset which specifies where the vertex data starts in the vertex buffer. In this case the data just starts at the beginning of the buffer.

 	const VkDeviceSize vertexOffsets[1] = { 0 };
 

Iterate through each created command buffer to record to it.

 	for (size_t i = 0; i < appManager.commandBuffers.size(); ++i)
 	{

Reset the buffer to its initial state.

 		vkResetCommandBuffer(appManager.commandBuffers[i], 0)
 

Begin the command buffer.

 		VkCommandBufferBeginInfo cmd_begin_info = {};
 		cmd_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
 		cmd_begin_info.pNext = nullptr;
 		cmd_begin_info.flags = 0;
 		cmd_begin_info.pInheritanceInfo = nullptr;
 
 		vkBeginCommandBuffer(appManager.commandBuffers[i], &cmd_begin_info)
 

Start recording commands.

In Vulkan, commands are recorded by calling vkCmd... functions.

Set the viewport and scissor to previously defined values.

 		vkCmdSetViewport(appManager.commandBuffers[i], 0, 1, &appManager.viewport);
 		
 		vkCmdSetScissor(appManager.commandBuffers[i], 0, 1, &appManager.scissor);
 

Begin the render pass.

The render pass and framebuffer instances are passed here, along with the clear colour value and the extents of the rendering area. VK_SUBPASS_CONTENTS_INLINE means that the subpass commands will be recorded here. The alternative is to record them in isolation in a secondary command buffer and then record them here with vkCmdExecuteCommands.

 		VkRenderPassBeginInfo renderPassInfo = {};
 		renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
 		renderPassInfo.pNext = nullptr;
 		renderPassInfo.renderPass = appManager.renderPass;
 		renderPassInfo.framebuffer = appManager.frameBuffers[i];
 		renderPassInfo.clearValueCount = 1;
 		renderPassInfo.pClearValues = &clearColor;
 		renderPassInfo.renderArea.extent = appManager.swapchainExtent;
 		renderPassInfo.renderArea.offset.x = 0;
 		renderPassInfo.renderArea.offset.y = 0;
 
 		vkCmdBeginRenderPass(appManager.commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
 

Bind the pipeline to the command buffer.

 		vkCmdBindPipeline(appManager.commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, appManager.pipeline);
 

A single large uniform buffer object is being used to hold all of the transformation matrices associated with the swapchain images. It is for this reason that only a single descriptor set is required for all of the frames.

 		const VkDescriptorSet descriptorSet[] = { appManager.staticDescSet, appManager.dynamicDescSet };
 		

An offset is used to select each slice of the uniform buffer object that contains the transformation matrix related to each swapchain image.

Calculate the offset into the uniform buffer object for the current slice.

 		uint32_t offset = static_cast<uint32_t>(appManager.dynamicUniformBufferData.bufferInfo.range * i);
 		

Bind the descriptor sets. The &offset parameter is the offset into the dynamic uniform buffer which is contained within the dynamic descriptor set.

 		vkCmdBindDescriptorSets(appManager.commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, appManager.pipelineLayout, 0, NUM_DESCRIPTOR_SETS, descriptorSet, 1, &offset);
 

Bind the vertex buffer.

 		vkCmdBindVertexBuffers(appManager.commandBuffers[i], 0, 1, &appManager.vertexBuffer.buffer, vertexOffsets);
 

Draw three vertices.

 		vkCmdDraw(appManager.commandBuffers[i], 3, 1, 0, 0);
 

End the render pass.

 		vkCmdEndRenderPass(appManager.commandBuffers[i]);
 

End the command buffer recording process.

 		vkEndCommandBuffer(appManager.commandBuffers[i])
 		

At this point the command buffer is ready to be submitted to a queue with all of the recorded operations executed asynchronously after that. A command buffer can, and if possible should, be executed multiple times, unless it is allocated with the VK_COMMAND_BUFFER_ONE_TIME_USE bit.

The command buffers recorded here will be reused across the lifetime of the application.

 	}