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() void VulkanExampleBase::createCommandBuffers()
{ {
// Create one command buffer per frame buffer // Create one command buffer for each swap chain image and reuse for rendering
// 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
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(
@ -103,18 +95,11 @@ void VulkanExampleBase::createCommandBuffers()
static_cast<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
// 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() void VulkanExampleBase::destroyCommandBuffers()
{ {
vkFreeCommandBuffers(device, cmdPool, static_cast<uint32_t>(drawCmdBuffers.size()), drawCmdBuffers.data()); 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() void VulkanExampleBase::createSetupCommandBuffer()
@ -220,7 +205,6 @@ void VulkanExampleBase::prepare()
createSetupCommandBuffer(); createSetupCommandBuffer();
setupSwapChain(); setupSwapChain();
createCommandBuffers(); createCommandBuffers();
buildPresentCommandBuffers();
setupDepthStencil(); setupDepthStencil();
setupRenderPass(); setupRenderPass();
createPipelineCache(); createPipelineCache();
@ -625,12 +609,6 @@ 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));
// 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() void VulkanExampleBase::submitFrame()
@ -667,12 +645,6 @@ void VulkanExampleBase::submitFrame()
submitInfo.pSignalSemaphores = &semaphores.renderComplete; 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(swapChain.queuePresent(queue, currentBuffer, submitTextOverlay ? semaphores.textOverlayComplete : semaphores.renderComplete));
VK_CHECK_RESULT(vkQueueWaitIdle(queue)); VK_CHECK_RESULT(vkQueueWaitIdle(queue));
@ -1472,72 +1444,6 @@ 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]));
}
}
void VulkanExampleBase::createCommandPool() void VulkanExampleBase::createCommandPool()
{ {
VkCommandPoolCreateInfo cmdPoolInfo = {}; VkCommandPoolCreateInfo cmdPoolInfo = {};
@ -1588,14 +1494,7 @@ void VulkanExampleBase::setupDepthStencil()
mem_alloc.allocationSize = memReqs.size; mem_alloc.allocationSize = memReqs.size;
mem_alloc.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 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(vkAllocateMemory(device, &mem_alloc, nullptr, &depthStencil.mem));
VK_CHECK_RESULT(vkBindImageMemory(device, depthStencil.image, depthStencil.mem, 0)); 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; depthStencilView.image = depthStencil.image;
VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &depthStencil.view)); VK_CHECK_RESULT(vkCreateImageView(device, &depthStencilView, nullptr, &depthStencil.view));
@ -1629,8 +1528,7 @@ void VulkanExampleBase::setupFrameBuffer()
void VulkanExampleBase::setupRenderPass() void VulkanExampleBase::setupRenderPass()
{ {
VkAttachmentDescription attachments[2] = {}; std::array<VkAttachmentDescription, 2> attachments = {};
// Color attachment // Color attachment
attachments[0].format = colorformat; attachments[0].format = colorformat;
attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; 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].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
// Depth attachment // Depth attachment
attachments[1].format = depthFormat; attachments[1].format = depthFormat;
attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; 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].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_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; attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkAttachmentReference colorReference = {}; VkAttachmentReference colorReference = {};
@ -1659,27 +1556,44 @@ void VulkanExampleBase::setupRenderPass()
depthReference.attachment = 1; depthReference.attachment = 1;
depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = {}; VkSubpassDescription subpassDescription = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.flags = 0; subpassDescription.colorAttachmentCount = 1;
subpass.inputAttachmentCount = 0; subpassDescription.pColorAttachments = &colorReference;
subpass.pInputAttachments = NULL; subpassDescription.pDepthStencilAttachment = &depthReference;
subpass.colorAttachmentCount = 1; subpassDescription.inputAttachmentCount = 0;
subpass.pColorAttachments = &colorReference; subpassDescription.pInputAttachments = nullptr;
subpass.pResolveAttachments = NULL; subpassDescription.preserveAttachmentCount = 0;
subpass.pDepthStencilAttachment = &depthReference; subpassDescription.pPreserveAttachments = nullptr;
subpass.preserveAttachmentCount = 0; subpassDescription.pResolveAttachments = nullptr;
subpass.pPreserveAttachments = NULL;
// 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 = {}; VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.pNext = NULL; renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
renderPassInfo.attachmentCount = 2; renderPassInfo.pAttachments = attachments.data();
renderPassInfo.pAttachments = attachments;
renderPassInfo.subpassCount = 1; renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass; renderPassInfo.pSubpasses = &subpassDescription;
renderPassInfo.dependencyCount = 0; renderPassInfo.dependencyCount = static_cast<uint32_t>(dependencies.size());
renderPassInfo.pDependencies = NULL; renderPassInfo.pDependencies = dependencies.data();
VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass)); VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass));
} }
@ -1718,7 +1632,6 @@ void VulkanExampleBase::windowResize()
destroyCommandBuffers(); destroyCommandBuffers();
createCommandBuffers(); createCommandBuffers();
buildCommandBuffers(); buildCommandBuffers();
buildPresentCommandBuffers();
vkQueueWaitIdle(queue); vkQueueWaitIdle(queue);
vkDeviceWaitIdle(device); vkDeviceWaitIdle(device);

View file

@ -104,10 +104,6 @@ protected:
VkCommandPool cmdPool; VkCommandPool cmdPool;
// 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
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 // 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
@ -248,9 +244,6 @@ 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();
// Creates a new (graphics) command pool object storing command buffers // Creates a new (graphics) command pool object storing command buffers
void createCommandPool(); void createCommandPool();
// Setup default depth and stencil views // Setup default depth and stencil views
@ -358,13 +351,11 @@ public:
// Prepare the frame for workload submission // Prepare the frame for workload submission
// - Acquires the next image from the swap chain // - Acquires the next image from the swap chain
// - Submits a post present barrier
// - Sets the default wait and signal semaphores // - Sets the default wait and signal semaphores
void prepareFrame(); void prepareFrame();
// Submit the frames' workload // Submit the frames' workload
// - Submits the text overlay (if enabled) // - Submits the text overlay (if enabled)
// -
void submitFrame(); void submitFrame();
}; };