Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions attachments/15_hello_triangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ class HelloTriangleApplication
}

void transition_image_layout(
uint32_t currentFrame,
uint32_t imageIndex,
vk::ImageLayout old_layout,
vk::ImageLayout new_layout,
vk::AccessFlags2 src_access_mask,
Expand All @@ -434,7 +434,7 @@ class HelloTriangleApplication
.newLayout = new_layout,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = swapChainImages[currentFrame],
.image = swapChainImages[imageIndex],
.subresourceRange = {
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
Expand Down
66 changes: 38 additions & 28 deletions attachments/16_frames_in_flight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,10 @@ class HelloTriangleApplication
vk::raii::CommandPool commandPool = nullptr;
std::vector<vk::raii::CommandBuffer> commandBuffers;

std::vector<vk::raii::Semaphore> presentCompleteSemaphore;
std::vector<vk::raii::Semaphore> renderFinishedSemaphore;
std::vector<vk::raii::Semaphore> presentCompleteSemaphores;
std::vector<vk::raii::Semaphore> renderFinishedSemaphores;
std::vector<vk::raii::Fence> inFlightFences;
uint32_t semaphoreIndex = 0;
uint32_t currentFrame = 0;
uint32_t frameIndex = 0;

std::vector<const char *> requiredDeviceExtension = {
vk::KHRSwapchainExtensionName,
Expand Down Expand Up @@ -377,7 +376,8 @@ class HelloTriangleApplication

void recordCommandBuffer(uint32_t imageIndex)
{
commandBuffers[currentFrame].begin({});
auto &commandBuffer = commandBuffers[frameIndex];
commandBuffer.begin({});
// Before starting rendering, transition the swapchain image to COLOR_ATTACHMENT_OPTIMAL
transition_image_layout(
imageIndex,
Expand All @@ -400,12 +400,12 @@ class HelloTriangleApplication
.layerCount = 1,
.colorAttachmentCount = 1,
.pColorAttachments = &attachmentInfo};
commandBuffers[currentFrame].beginRendering(renderingInfo);
commandBuffers[currentFrame].bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline);
commandBuffers[currentFrame].setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(swapChainExtent.width), static_cast<float>(swapChainExtent.height), 0.0f, 1.0f));
commandBuffers[currentFrame].setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent));
commandBuffers[currentFrame].draw(3, 1, 0, 0);
commandBuffers[currentFrame].endRendering();
commandBuffer.beginRendering(renderingInfo);
commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline);
commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(swapChainExtent.width), static_cast<float>(swapChainExtent.height), 0.0f, 1.0f));
commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent));
commandBuffer.draw(3, 1, 0, 0);
commandBuffer.endRendering();
// After rendering, transition the swapchain image to PRESENT_SRC
transition_image_layout(
imageIndex,
Expand All @@ -416,7 +416,7 @@ class HelloTriangleApplication
vk::PipelineStageFlagBits2::eColorAttachmentOutput, // srcStage
vk::PipelineStageFlagBits2::eBottomOfPipe // dstStage
);
commandBuffers[currentFrame].end();
commandBuffer.end();
}

void transition_image_layout(
Expand Down Expand Up @@ -448,42 +448,53 @@ class HelloTriangleApplication
.dependencyFlags = {},
.imageMemoryBarrierCount = 1,
.pImageMemoryBarriers = &barrier};
commandBuffers[currentFrame].pipelineBarrier2(dependency_info);
commandBuffers[frameIndex].pipelineBarrier2(dependency_info);
}

void createSyncObjects()
{
presentCompleteSemaphore.clear();
renderFinishedSemaphore.clear();
inFlightFences.clear();
assert(presentCompleteSemaphores.empty() && renderFinishedSemaphores.empty() && inFlightFences.empty());

for (size_t i = 0; i < swapChainImages.size(); i++)
{
presentCompleteSemaphore.emplace_back(device, vk::SemaphoreCreateInfo());
renderFinishedSemaphore.emplace_back(device, vk::SemaphoreCreateInfo());
renderFinishedSemaphores.emplace_back(device, vk::SemaphoreCreateInfo());
}

for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
{
presentCompleteSemaphores.emplace_back(device, vk::SemaphoreCreateInfo());
inFlightFences.emplace_back(device, vk::FenceCreateInfo{.flags = vk::FenceCreateFlagBits::eSignaled});
}
}

void drawFrame()
{
while (vk::Result::eTimeout == device.waitForFences(*inFlightFences[currentFrame], vk::True, UINT64_MAX))
// Note: inFlightFences, presentCompleteSemaphores, and commandBuffers are indexed by frameIndex,
// while renderFinishedSemaphores is indexed by imageIndex
while (vk::Result::eTimeout == device.waitForFences(*inFlightFences[frameIndex], vk::True, UINT64_MAX))
;
auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphore[semaphoreIndex], nullptr);
device.resetFences(*inFlightFences[frameIndex]);

device.resetFences(*inFlightFences[currentFrame]);
commandBuffers[currentFrame].reset();
auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr);

commandBuffers[frameIndex].reset();
recordCommandBuffer(imageIndex);

vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput);
const vk::SubmitInfo submitInfo{.waitSemaphoreCount = 1, .pWaitSemaphores = &*presentCompleteSemaphore[semaphoreIndex], .pWaitDstStageMask = &waitDestinationStageMask, .commandBufferCount = 1, .pCommandBuffers = &*commandBuffers[currentFrame], .signalSemaphoreCount = 1, .pSignalSemaphores = &*renderFinishedSemaphore[imageIndex]};
queue.submit(submitInfo, *inFlightFences[currentFrame]);

const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, .pWaitSemaphores = &*renderFinishedSemaphore[imageIndex], .swapchainCount = 1, .pSwapchains = &*swapChain, .pImageIndices = &imageIndex};
const vk::SubmitInfo submitInfo{.waitSemaphoreCount = 1,
.pWaitSemaphores = &*presentCompleteSemaphores[frameIndex],
.pWaitDstStageMask = &waitDestinationStageMask,
.commandBufferCount = 1,
.pCommandBuffers = &*commandBuffers[frameIndex],
.signalSemaphoreCount = 1,
.pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]};
queue.submit(submitInfo, *inFlightFences[frameIndex]);

const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1,
.pWaitSemaphores = &*renderFinishedSemaphores[imageIndex],
.swapchainCount = 1,
.pSwapchains = &*swapChain,
.pImageIndices = &imageIndex};
result = queue.presentKHR(presentInfoKHR);
switch (result)
{
Expand All @@ -495,8 +506,7 @@ class HelloTriangleApplication
default:
break; // an unexpected result is returned!
}
semaphoreIndex = (semaphoreIndex + 1) % presentCompleteSemaphore.size();
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT;
}

[[nodiscard]] vk::raii::ShaderModule createShaderModule(const std::vector<char> &code) const
Expand Down
67 changes: 39 additions & 28 deletions attachments/17_swap_chain_recreation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,10 @@ class HelloTriangleApplication
vk::raii::CommandPool commandPool = nullptr;
std::vector<vk::raii::CommandBuffer> commandBuffers;

std::vector<vk::raii::Semaphore> presentCompleteSemaphore;
std::vector<vk::raii::Semaphore> renderFinishedSemaphore;
std::vector<vk::raii::Semaphore> presentCompleteSemaphores;
std::vector<vk::raii::Semaphore> renderFinishedSemaphores;
std::vector<vk::raii::Fence> inFlightFences;
uint32_t semaphoreIndex = 0;
uint32_t currentFrame = 0;
uint32_t frameIndex = 0;

bool framebufferResized = false;

Expand Down Expand Up @@ -411,7 +410,8 @@ class HelloTriangleApplication

void recordCommandBuffer(uint32_t imageIndex)
{
commandBuffers[currentFrame].begin({});
auto &commandBuffer = commandBuffers[frameIndex];
commandBuffer.begin({});
// Before starting rendering, transition the swapchain image to COLOR_ATTACHMENT_OPTIMAL
transition_image_layout(
imageIndex,
Expand All @@ -434,12 +434,12 @@ class HelloTriangleApplication
.layerCount = 1,
.colorAttachmentCount = 1,
.pColorAttachments = &attachmentInfo};
commandBuffers[currentFrame].beginRendering(renderingInfo);
commandBuffers[currentFrame].bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline);
commandBuffers[currentFrame].setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(swapChainExtent.width), static_cast<float>(swapChainExtent.height), 0.0f, 1.0f));
commandBuffers[currentFrame].setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent));
commandBuffers[currentFrame].draw(3, 1, 0, 0);
commandBuffers[currentFrame].endRendering();
commandBuffer.beginRendering(renderingInfo);
commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, *graphicsPipeline);
commandBuffer.setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(swapChainExtent.width), static_cast<float>(swapChainExtent.height), 0.0f, 1.0f));
commandBuffer.setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), swapChainExtent));
commandBuffer.draw(3, 1, 0, 0);
commandBuffer.endRendering();
// After rendering, transition the swapchain image to PRESENT_SRC
transition_image_layout(
imageIndex,
Expand All @@ -450,7 +450,7 @@ class HelloTriangleApplication
vk::PipelineStageFlagBits2::eColorAttachmentOutput, // srcStage
vk::PipelineStageFlagBits2::eBottomOfPipe // dstStage
);
commandBuffers[currentFrame].end();
commandBuffer.end();
}

void transition_image_layout(
Expand Down Expand Up @@ -482,32 +482,34 @@ class HelloTriangleApplication
.dependencyFlags = {},
.imageMemoryBarrierCount = 1,
.pImageMemoryBarriers = &barrier};
commandBuffers[currentFrame].pipelineBarrier2(dependency_info);
commandBuffers[frameIndex].pipelineBarrier2(dependency_info);
}

void createSyncObjects()
{
presentCompleteSemaphore.clear();
renderFinishedSemaphore.clear();
inFlightFences.clear();
assert(presentCompleteSemaphores.empty() && renderFinishedSemaphores.empty() && inFlightFences.empty());

for (size_t i = 0; i < swapChainImages.size(); i++)
{
presentCompleteSemaphore.emplace_back(device, vk::SemaphoreCreateInfo());
renderFinishedSemaphore.emplace_back(device, vk::SemaphoreCreateInfo());
renderFinishedSemaphores.emplace_back(device, vk::SemaphoreCreateInfo());
}

for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
{
presentCompleteSemaphores.emplace_back(device, vk::SemaphoreCreateInfo());
inFlightFences.emplace_back(device, vk::FenceCreateInfo{.flags = vk::FenceCreateFlagBits::eSignaled});
}
}

void drawFrame()
{
while (vk::Result::eTimeout == device.waitForFences(*inFlightFences[currentFrame], vk::True, UINT64_MAX))
// Note: inFlightFences, presentCompleteSemaphores, and commandBuffers are indexed by frameIndex,
// while renderFinishedSemaphores is indexed by imageIndex
while (vk::Result::eTimeout == device.waitForFences(*inFlightFences[frameIndex], vk::True, UINT64_MAX))
;
auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphore[semaphoreIndex], nullptr);
device.resetFences(*inFlightFences[frameIndex]);

auto [result, imageIndex] = swapChain.acquireNextImage(UINT64_MAX, *presentCompleteSemaphores[frameIndex], nullptr);

if (result == vk::Result::eErrorOutOfDateKHR)
{
Expand All @@ -519,19 +521,29 @@ class HelloTriangleApplication
throw std::runtime_error("failed to acquire swap chain image!");
}

device.resetFences(*inFlightFences[currentFrame]);
commandBuffers[currentFrame].reset();
device.resetFences(*inFlightFences[frameIndex]);
commandBuffers[frameIndex].reset();
recordCommandBuffer(imageIndex);

vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput);
const vk::SubmitInfo submitInfo{.waitSemaphoreCount = 1, .pWaitSemaphores = &*presentCompleteSemaphore[semaphoreIndex], .pWaitDstStageMask = &waitDestinationStageMask, .commandBufferCount = 1, .pCommandBuffers = &*commandBuffers[currentFrame], .signalSemaphoreCount = 1, .pSignalSemaphores = &*renderFinishedSemaphore[imageIndex]};
queue.submit(submitInfo, *inFlightFences[currentFrame]);
const vk::SubmitInfo submitInfo{.waitSemaphoreCount = 1,
.pWaitSemaphores = &*presentCompleteSemaphores[frameIndex],
.pWaitDstStageMask = &waitDestinationStageMask,
.commandBufferCount = 1,
.pCommandBuffers = &*commandBuffers[frameIndex],
.signalSemaphoreCount = 1,
.pSignalSemaphores = &*renderFinishedSemaphores[imageIndex]};
queue.submit(submitInfo, *inFlightFences[frameIndex]);

try
{
const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1, .pWaitSemaphores = &*renderFinishedSemaphore[imageIndex], .swapchainCount = 1, .pSwapchains = &*swapChain, .pImageIndices = &imageIndex};
const vk::PresentInfoKHR presentInfoKHR{.waitSemaphoreCount = 1,
.pWaitSemaphores = &*renderFinishedSemaphores[imageIndex],
.swapchainCount = 1,
.pSwapchains = &*swapChain,
.pImageIndices = &imageIndex};
result = queue.presentKHR(presentInfoKHR);
if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || framebufferResized)
if (result == vk::Result::eSuboptimalKHR || framebufferResized)
{
framebufferResized = false;
recreateSwapChain();
Expand All @@ -553,8 +565,7 @@ class HelloTriangleApplication
throw;
}
}
semaphoreIndex = (semaphoreIndex + 1) % presentCompleteSemaphore.size();
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
frameIndex = (frameIndex + 1) % MAX_FRAMES_IN_FLIGHT;
}

[[nodiscard]] vk::raii::ShaderModule createShaderModule(const std::vector<char> &code) const
Expand Down
Loading
Loading