diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index 7c1437cf..49c72f64 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -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(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(drawCmdBuffers.size()), drawCmdBuffers.data()); - vkFreeCommandBuffers(device, cmdPool, static_cast(drawCmdBuffers.size()), prePresentCmdBuffers.data()); - vkFreeCommandBuffers(device, cmdPool, static_cast(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, ¤tBuffer)); - - // 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 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 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(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(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); diff --git a/base/vulkanexamplebase.h b/base/vulkanexamplebase.h index ed1760fd..0f4ce27f 100644 --- a/base/vulkanexamplebase.h +++ b/base/vulkanexamplebase.h @@ -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 postPresentCmdBuffers = { VK_NULL_HANDLE }; - // Command buffers for submitting a pre present image barrier - std::vector 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(); };