Fold attachment layout transitions into subpass (Refs #155)

This commit is contained in:
saschawillems 2016-08-10 20:39:01 +02:00
parent a56f2b2c6f
commit bc8cae9db7
2 changed files with 39 additions and 135 deletions

View file

@ -85,16 +85,8 @@ bool VulkanExampleBase::checkCommandBuffers()
void VulkanExampleBase::createCommandBuffers()
{
// Create one command buffer per frame buffer
// in the swap chain
// Command buffers store a reference to the
// frame buffer inside their render pass info
// so for static usage withouth having to rebuild
// them each frame, we use one per frame buffer
// Create one command buffer for each swap chain image and reuse for rendering
drawCmdBuffers.resize(swapChain.imageCount);
prePresentCmdBuffers.resize(swapChain.imageCount);
postPresentCmdBuffers.resize(swapChain.imageCount);
VkCommandBufferAllocateInfo cmdBufAllocateInfo =
vkTools::initializers::commandBufferAllocateInfo(
@ -103,18 +95,11 @@ void VulkanExampleBase::createCommandBuffers()
static_cast<uint32_t>(drawCmdBuffers.size()));
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, drawCmdBuffers.data()));
// Command buffers for submitting present barriers
// 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, 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()
@ -220,7 +205,6 @@ void VulkanExampleBase::prepare()
createSetupCommandBuffer();
setupSwapChain();
createCommandBuffers();
buildPresentCommandBuffers();
setupDepthStencil();
setupRenderPass();
createPipelineCache();
@ -625,12 +609,6 @@ void VulkanExampleBase::prepareFrame()
{
// Acquire the next image from the swap chaing
VK_CHECK_RESULT(swapChain.acquireNextImage(semaphores.presentComplete, &currentBuffer));
// 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 = &postPresentCmdBuffers[currentBuffer];
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
}
void VulkanExampleBase::submitFrame()
@ -667,12 +645,6 @@ void VulkanExampleBase::submitFrame()
submitInfo.pSignalSemaphores = &semaphores.renderComplete;
}
// 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 = &prePresentCmdBuffers[currentBuffer];
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(vkQueueWaitIdle(queue));
@ -1472,72 +1444,6 @@ 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]));
}
}
void VulkanExampleBase::createCommandPool()
{
VkCommandPoolCreateInfo cmdPoolInfo = {};
@ -1588,14 +1494,7 @@ void VulkanExampleBase::setupDepthStencil()
mem_alloc.allocationSize = memReqs.size;
mem_alloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VK_CHECK_RESULT(vkAllocateMemory(device, &mem_alloc, nullptr, &depthStencil.mem));
VK_CHECK_RESULT(vkBindImageMemory(device, depthStencil.image, depthStencil.mem, 0));
vkTools::setImageLayout(
setupCmdBuffer,
depthStencil.image,
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
depthStencilView.image = depthStencil.image;
VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &depthStencil.view));
@ -1629,8 +1528,7 @@ void VulkanExampleBase::setupFrameBuffer()
void VulkanExampleBase::setupRenderPass()
{
VkAttachmentDescription attachments[2] = {};
std::array<VkAttachmentDescription, 2> attachments = {};
// Color attachment
attachments[0].format = colorformat;
attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
@ -1638,9 +1536,8 @@ void VulkanExampleBase::setupRenderPass()
attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
// Depth attachment
attachments[1].format = depthFormat;
attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
@ -1648,7 +1545,7 @@ void VulkanExampleBase::setupRenderPass()
attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkAttachmentReference colorReference = {};
@ -1659,27 +1556,44 @@ void VulkanExampleBase::setupRenderPass()
depthReference.attachment = 1;
depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.flags = 0;
subpass.inputAttachmentCount = 0;
subpass.pInputAttachments = NULL;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorReference;
subpass.pResolveAttachments = NULL;
subpass.pDepthStencilAttachment = &depthReference;
subpass.preserveAttachmentCount = 0;
subpass.pPreserveAttachments = NULL;
VkSubpassDescription subpassDescription = {};
subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpassDescription.colorAttachmentCount = 1;
subpassDescription.pColorAttachments = &colorReference;
subpassDescription.pDepthStencilAttachment = &depthReference;
subpassDescription.inputAttachmentCount = 0;
subpassDescription.pInputAttachments = nullptr;
subpassDescription.preserveAttachmentCount = 0;
subpassDescription.pPreserveAttachments = nullptr;
subpassDescription.pResolveAttachments = nullptr;
// Subpass dependencies for layout transitions
std::array<VkSubpassDependency, 2> dependencies;
dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependencies[0].dstSubpass = 0;
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
dependencies[1].srcSubpass = 0;
dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.pNext = NULL;
renderPassInfo.attachmentCount = 2;
renderPassInfo.pAttachments = attachments;
renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
renderPassInfo.pAttachments = attachments.data();
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
renderPassInfo.dependencyCount = 0;
renderPassInfo.pDependencies = NULL;
renderPassInfo.pSubpasses = &subpassDescription;
renderPassInfo.dependencyCount = static_cast<uint32_t>(dependencies.size());
renderPassInfo.pDependencies = dependencies.data();
VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass));
}
@ -1718,7 +1632,6 @@ void VulkanExampleBase::windowResize()
destroyCommandBuffers();
createCommandBuffers();
buildCommandBuffers();
buildPresentCommandBuffers();
vkQueueWaitIdle(queue);
vkDeviceWaitIdle(device);

View file

@ -104,10 +104,6 @@ protected:
VkCommandPool cmdPool;
// Command buffer used for setup
VkCommandBuffer setupCmdBuffer = VK_NULL_HANDLE;
// Command buffer for submitting a post present image barrier
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
@ -248,9 +244,6 @@ public:
// all command buffers that may reference this
virtual void buildCommandBuffers();
// Builds the command buffers used to submit the present barriers
void buildPresentCommandBuffers();
// Creates a new (graphics) command pool object storing command buffers
void createCommandPool();
// Setup default depth and stencil views
@ -358,13 +351,11 @@ public:
// Prepare the frame for workload submission
// - Acquires the next image from the swap chain
// - Submits a post present barrier
// - Sets the default wait and signal semaphores
void prepareFrame();
// Submit the frames' workload
// - Submits the text overlay (if enabled)
// -
void submitFrame();
};