Build command buffers for pre and post present barriers only once (instead of every frame)

This commit is contained in:
saschawillems 2016-06-21 23:07:16 +02:00
parent d944af8604
commit 8f76a24e53
3 changed files with 134 additions and 51 deletions

View file

@ -121,28 +121,28 @@ void VulkanExampleBase::createCommandBuffers()
// them each frame, we use one per frame buffer
drawCmdBuffers.resize(swapChain.imageCount);
prePresentCmdBuffers.resize(swapChain.imageCount);
postPresentCmdBuffers.resize(swapChain.imageCount);
VkCommandBufferAllocateInfo cmdBufAllocateInfo =
vkTools::initializers::commandBufferAllocateInfo(
cmdPool,
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
(uint32_t)drawCmdBuffers.size());
static_cast<uint32_t>(drawCmdBuffers.size()));
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, drawCmdBuffers.data()));
// Command buffers for submitting present barriers
cmdBufAllocateInfo.commandBufferCount = 1;
// Pre present
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &prePresentCmdBuffer));
// Post present
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &postPresentCmdBuffer));
// One pre and post present buffer per swap chain image
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, prePresentCmdBuffers.data()));
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, postPresentCmdBuffers.data()));
}
void VulkanExampleBase::destroyCommandBuffers()
{
vkFreeCommandBuffers(device, cmdPool, (uint32_t)drawCmdBuffers.size(), drawCmdBuffers.data());
vkFreeCommandBuffers(device, cmdPool, 1, &prePresentCmdBuffer);
vkFreeCommandBuffers(device, cmdPool, 1, &postPresentCmdBuffer);
vkFreeCommandBuffers(device, cmdPool, static_cast<uint32_t>(drawCmdBuffers.size()), drawCmdBuffers.data());
vkFreeCommandBuffers(device, cmdPool, static_cast<uint32_t>(drawCmdBuffers.size()), prePresentCmdBuffers.data());
vkFreeCommandBuffers(device, cmdPool, static_cast<uint32_t>(drawCmdBuffers.size()), postPresentCmdBuffers.data());
}
void VulkanExampleBase::createSetupCommandBuffer()
@ -256,6 +256,7 @@ void VulkanExampleBase::prepare()
createSetupCommandBuffer();
setupSwapChain();
createCommandBuffers();
buildPresentCommandBuffers();
setupDepthStencil();
setupRenderPass();
createPipelineCache();
@ -645,7 +646,7 @@ void VulkanExampleBase::prepareFrame()
{
// Acquire the next image from the swap chaing
VK_CHECK_RESULT(swapChain.acquireNextImage(semaphores.presentComplete, &currentBuffer));
/*
// Insert a post present image barrier to transform the image back to a
// color attachment that our render pass can write to
// We always use undefined image layout as the source as it doesn't actually matter
@ -673,9 +674,12 @@ void VulkanExampleBase::prepareFrame()
1, &postPresentBarrier);
VK_CHECK_RESULT(vkEndCommandBuffer(postPresentCmdBuffer));
*/
// Submit post present image barrier to transform the image back to a color attachment that our render pass can write to
VkSubmitInfo submitInfo = vkTools::initializers::submitInfo();
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &postPresentCmdBuffer;
submitInfo.pCommandBuffers = &postPresentCmdBuffers[currentBuffer];
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
}
@ -715,6 +719,7 @@ void VulkanExampleBase::submitFrame()
// Submit a pre present image barrier to the queue
// Transforms the (framebuffer) image layout from color attachment to present(khr) for presenting to the swap chain
/*
VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo();
VK_CHECK_RESULT(vkBeginCommandBuffer(prePresentCmdBuffer, &cmdBufInfo));
@ -738,9 +743,11 @@ void VulkanExampleBase::submitFrame()
1, &prePresentBarrier);
VK_CHECK_RESULT(vkEndCommandBuffer(prePresentCmdBuffer));
*/
// Submit pre present image barrier to transform the image from color attachment to present(khr) for presenting to the swap chain
VkSubmitInfo submitInfo = vkTools::initializers::submitInfo();
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &prePresentCmdBuffer;
submitInfo.pCommandBuffers = &prePresentCmdBuffers[currentBuffer];
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
VK_CHECK_RESULT(swapChain.queuePresent(queue, currentBuffer, submitTextOverlay ? semaphores.textOverlayComplete : semaphores.renderComplete));
@ -1504,6 +1511,72 @@ void VulkanExampleBase::buildCommandBuffers()
// Can be overriden in derived class
}
void VulkanExampleBase::buildPresentCommandBuffers()
{
VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo();
for (uint32_t i = 0; i < swapChain.imageCount; i++)
{
// Command buffer for post present barrier
// Insert a post present image barrier to transform the image back to a
// color attachment that our render pass can write to
// We always use undefined image layout as the source as it doesn't actually matter
// what is done with the previous image contents
VK_CHECK_RESULT(vkBeginCommandBuffer(postPresentCmdBuffers[i], &cmdBufInfo));
VkImageMemoryBarrier postPresentBarrier = vkTools::initializers::imageMemoryBarrier();
postPresentBarrier.srcAccessMask = 0;
postPresentBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
postPresentBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
postPresentBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
postPresentBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
postPresentBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
postPresentBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
postPresentBarrier.image = swapChain.buffers[i].image;
vkCmdPipelineBarrier(
postPresentCmdBuffers[i],
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
0,
0, nullptr,
0, nullptr,
1, &postPresentBarrier);
VK_CHECK_RESULT(vkEndCommandBuffer(postPresentCmdBuffers[i]));
// Command buffers for pre present barrier
// Submit a pre present image barrier to the queue
// Transforms the (framebuffer) image layout from color attachment to present(khr) for presenting to the swap chain
VK_CHECK_RESULT(vkBeginCommandBuffer(prePresentCmdBuffers[i], &cmdBufInfo));
VkImageMemoryBarrier prePresentBarrier = vkTools::initializers::imageMemoryBarrier();
prePresentBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
prePresentBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
prePresentBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
prePresentBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
prePresentBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
prePresentBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
prePresentBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
prePresentBarrier.image = swapChain.buffers[i].image;
vkCmdPipelineBarrier(
prePresentCmdBuffers[i],
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_FLAGS_NONE,
0, nullptr, // No memory barriers,
0, nullptr, // No buffer barriers,
1, &prePresentBarrier);
VK_CHECK_RESULT(vkEndCommandBuffer(prePresentCmdBuffers[i]));
}
}
VkBool32 VulkanExampleBase::getMemoryType(uint32_t typeBits, VkFlags properties, uint32_t * typeIndex)
{
for (uint32_t i = 0; i < 32; i++)
@ -1719,6 +1792,7 @@ void VulkanExampleBase::windowResize()
destroyCommandBuffers();
createCommandBuffers();
buildCommandBuffers();
buildPresentCommandBuffers();
vkQueueWaitIdle(queue);
vkDeviceWaitIdle(device);

View file

@ -102,9 +102,9 @@ protected:
// Command buffer used for setup
VkCommandBuffer setupCmdBuffer = VK_NULL_HANDLE;
// Command buffer for submitting a post present image barrier
VkCommandBuffer postPresentCmdBuffer = VK_NULL_HANDLE;
// Command buffer for submitting a pre present image barrier
VkCommandBuffer prePresentCmdBuffer = VK_NULL_HANDLE;
std::vector<VkCommandBuffer> postPresentCmdBuffers = { VK_NULL_HANDLE };
// Command buffers for submitting a pre present image barrier
std::vector<VkCommandBuffer> prePresentCmdBuffers = { VK_NULL_HANDLE };
// Pipeline stage flags for the submit info structure
VkPipelineStageFlags submitPipelineStages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
// Contains command buffers and semaphores to be presented to the queue
@ -246,6 +246,9 @@ public:
// all command buffers that may reference this
virtual void buildCommandBuffers();
// Builds the command buffers used to submit the present barriers
void buildPresentCommandBuffers();
// Get memory type for a given memory allocation (flags and bits)
VkBool32 getMemoryType(uint32_t typeBits, VkFlags properties, uint32_t *typeIndex);
uint32_t getMemoryType(uint32_t typeBits, VkFlags properties);

View file

@ -292,13 +292,12 @@ public:
VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i]));
}
}
void draw()
// Build command buffers for the post present image barrier for each swap chain image
// Note: The command Buffers are allocated in the base class
for (uint32_t i = 0; i < swapChain.imageCount; i++)
{
// Get next image in the swap chain (back/front buffer)
VK_CHECK_RESULT(swapChain.acquireNextImage(semaphores.presentComplete, &currentBuffer));
// Insert a post present image barrier to transform the image back to a
// color attachment that our render pass can write to
// We always use undefined image layout as the source as it doesn't actually matter
@ -311,17 +310,17 @@ public:
postPresentBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
postPresentBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
postPresentBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
postPresentBarrier.image = swapChain.buffers[currentBuffer].image;
postPresentBarrier.image = swapChain.buffers[i].image;
// Use dedicated command buffer from example base class for submitting the post present barrier
VkCommandBufferBeginInfo cmdBufInfo = {};
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
VK_CHECK_RESULT(vkBeginCommandBuffer(postPresentCmdBuffer, &cmdBufInfo));
VK_CHECK_RESULT(vkBeginCommandBuffer(postPresentCmdBuffers[i], &cmdBufInfo));
// Put post present barrier into command buffer
vkCmdPipelineBarrier(
postPresentCmdBuffer,
postPresentCmdBuffers[i],
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_FLAGS_NONE,
@ -329,13 +328,21 @@ public:
0, nullptr,
1, &postPresentBarrier);
VK_CHECK_RESULT(vkEndCommandBuffer(postPresentCmdBuffer));
VK_CHECK_RESULT(vkEndCommandBuffer(postPresentCmdBuffers[i]));
}
}
// Submit the image barrier to the current queue
submitInfo = {};
void draw()
{
// Get next image in the swap chain (back/front buffer)
VK_CHECK_RESULT(swapChain.acquireNextImage(semaphores.presentComplete, &currentBuffer));
// Submit the post present image barrier to transform the image back to a color attachment
// that can be used to write to by our render pass
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &postPresentCmdBuffer;
submitInfo.pCommandBuffers = &postPresentCmdBuffers[currentBuffer];
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
@ -347,7 +354,6 @@ public:
// command buffers and semaphores to be submitted to a queue
// If you want to submit multiple command buffers, pass an array
VkPipelineStageFlags pipelineStages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pWaitDstStageMask = &pipelineStages;
// The wait semaphore ensures that the image is presented