Skip to content
Open
Show file tree
Hide file tree
Changes from all 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