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 // them each frame, we use one per frame buffer
drawCmdBuffers.resize(swapChain.imageCount); drawCmdBuffers.resize(swapChain.imageCount);
prePresentCmdBuffers.resize(swapChain.imageCount);
postPresentCmdBuffers.resize(swapChain.imageCount);
VkCommandBufferAllocateInfo cmdBufAllocateInfo = VkCommandBufferAllocateInfo cmdBufAllocateInfo =
vkTools::initializers::commandBufferAllocateInfo( vkTools::initializers::commandBufferAllocateInfo(
cmdPool, cmdPool,
VK_COMMAND_BUFFER_LEVEL_PRIMARY, VK_COMMAND_BUFFER_LEVEL_PRIMARY,
(uint32_t)drawCmdBuffers.size()); static_cast<uint32_t>(drawCmdBuffers.size()));
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, drawCmdBuffers.data())); VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, drawCmdBuffers.data()));
// Command buffers for submitting present barriers // Command buffers for submitting present barriers
cmdBufAllocateInfo.commandBufferCount = 1; // One pre and post present buffer per swap chain image
// Pre present VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, prePresentCmdBuffers.data()));
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &prePresentCmdBuffer)); VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, postPresentCmdBuffers.data()));
// Post present
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &postPresentCmdBuffer));
} }
void VulkanExampleBase::destroyCommandBuffers() void VulkanExampleBase::destroyCommandBuffers()
{ {
vkFreeCommandBuffers(device, cmdPool, (uint32_t)drawCmdBuffers.size(), drawCmdBuffers.data()); vkFreeCommandBuffers(device, cmdPool, static_cast<uint32_t>(drawCmdBuffers.size()), drawCmdBuffers.data());
vkFreeCommandBuffers(device, cmdPool, 1, &prePresentCmdBuffer); vkFreeCommandBuffers(device, cmdPool, static_cast<uint32_t>(drawCmdBuffers.size()), prePresentCmdBuffers.data());
vkFreeCommandBuffers(device, cmdPool, 1, &postPresentCmdBuffer); vkFreeCommandBuffers(device, cmdPool, static_cast<uint32_t>(drawCmdBuffers.size()), postPresentCmdBuffers.data());
} }
void VulkanExampleBase::createSetupCommandBuffer() void VulkanExampleBase::createSetupCommandBuffer()
@ -256,6 +256,7 @@ void VulkanExampleBase::prepare()
createSetupCommandBuffer(); createSetupCommandBuffer();
setupSwapChain(); setupSwapChain();
createCommandBuffers(); createCommandBuffers();
buildPresentCommandBuffers();
setupDepthStencil(); setupDepthStencil();
setupRenderPass(); setupRenderPass();
createPipelineCache(); createPipelineCache();
@ -645,7 +646,7 @@ void VulkanExampleBase::prepareFrame()
{ {
// Acquire the next image from the swap chaing // Acquire the next image from the swap chaing
VK_CHECK_RESULT(swapChain.acquireNextImage(semaphores.presentComplete, &currentBuffer)); VK_CHECK_RESULT(swapChain.acquireNextImage(semaphores.presentComplete, &currentBuffer));
/*
// Insert a post present image barrier to transform the image back to a // Insert a post present image barrier to transform the image back to a
// color attachment that our render pass can write to // color attachment that our render pass can write to
// We always use undefined image layout as the source as it doesn't actually matter // We always use undefined image layout as the source as it doesn't actually matter
@ -673,9 +674,12 @@ void VulkanExampleBase::prepareFrame()
1, &postPresentBarrier); 1, &postPresentBarrier);
VK_CHECK_RESULT(vkEndCommandBuffer(postPresentCmdBuffer)); 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(); VkSubmitInfo submitInfo = vkTools::initializers::submitInfo();
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &postPresentCmdBuffer; submitInfo.pCommandBuffers = &postPresentCmdBuffers[currentBuffer];
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); 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 // 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 // Transforms the (framebuffer) image layout from color attachment to present(khr) for presenting to the swap chain
/*
VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo(); VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo();
VK_CHECK_RESULT(vkBeginCommandBuffer(prePresentCmdBuffer, &cmdBufInfo)); VK_CHECK_RESULT(vkBeginCommandBuffer(prePresentCmdBuffer, &cmdBufInfo));
@ -738,9 +743,11 @@ void VulkanExampleBase::submitFrame()
1, &prePresentBarrier); 1, &prePresentBarrier);
VK_CHECK_RESULT(vkEndCommandBuffer(prePresentCmdBuffer)); 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(); VkSubmitInfo submitInfo = vkTools::initializers::submitInfo();
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &prePresentCmdBuffer; submitInfo.pCommandBuffers = &prePresentCmdBuffers[currentBuffer];
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
VK_CHECK_RESULT(swapChain.queuePresent(queue, currentBuffer, submitTextOverlay ? semaphores.textOverlayComplete : semaphores.renderComplete)); 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 // 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) VkBool32 VulkanExampleBase::getMemoryType(uint32_t typeBits, VkFlags properties, uint32_t * typeIndex)
{ {
for (uint32_t i = 0; i < 32; i++) for (uint32_t i = 0; i < 32; i++)
@ -1719,6 +1792,7 @@ void VulkanExampleBase::windowResize()
destroyCommandBuffers(); destroyCommandBuffers();
createCommandBuffers(); createCommandBuffers();
buildCommandBuffers(); buildCommandBuffers();
buildPresentCommandBuffers();
vkQueueWaitIdle(queue); vkQueueWaitIdle(queue);
vkDeviceWaitIdle(device); vkDeviceWaitIdle(device);

View file

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

View file

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