1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
|
#include "RenderFrame.h"
namespace graphics {
namespace vulkan {
RenderFrame::RenderFrame(vk::Device device, vk::SwapchainKHR swapChain, vk::Queue graphicsQueue, vk::Queue presentQueue)
: m_device(device), m_swapChain(swapChain), m_graphicsQueue(graphicsQueue), m_presentQueue(presentQueue)
{
constexpr vk::SemaphoreCreateInfo semaphoreCreateInfo;
constexpr vk::FenceCreateInfo fenceCreateInfo;
m_imageAvailableSemaphore = device.createSemaphoreUnique(semaphoreCreateInfo);
m_renderingFinishedSemaphore = device.createSemaphoreUnique(semaphoreCreateInfo);
m_frameInFlightFence = device.createFenceUnique(fenceCreateInfo);
}
void RenderFrame::waitForFinish()
{
if (!m_inFlight) {
return;
}
m_device.waitForFences(m_frameInFlightFence.get(), true, std::numeric_limits<uint64_t>::max());
m_device.resetFences(m_frameInFlightFence.get());
// That frame is now definitely not in flight anymore so we can call the functions that depend on that
for (const auto& finishFunc : m_frameFinishedCallbacks) {
finishFunc();
}
m_frameFinishedCallbacks.clear();
// Our fence has been signaled so we are no longer in flight and ready to be reused
m_inFlight = false;
}
void RenderFrame::onFrameFinished(std::function<void()> finishFunc)
{
m_frameFinishedCallbacks.push_back(std::move(finishFunc));
}
uint32_t RenderFrame::acquireSwapchainImage()
{
Assertion(!m_inFlight, "Cannot acquire swapchain image when frame is still in flight.");
uint32_t imageIndex;
m_device.acquireNextImageKHR(m_swapChain,
std::numeric_limits<uint64_t>::max(),
m_imageAvailableSemaphore.get(),
nullptr,
&imageIndex);
m_swapChainIdx = imageIndex;
return imageIndex;
}
void RenderFrame::submitAndPresent(const std::vector<vk::CommandBuffer>& cmdBuffers)
{
Assertion(!m_inFlight, "Cannot submit a frame for presentation when it is still in flight.");
const std::array<vk::PipelineStageFlags, 1> waitStages = {vk::PipelineStageFlagBits::eColorAttachmentOutput};
const std::array<vk::Semaphore, 1> waitSemaphores = {m_imageAvailableSemaphore.get()};
vk::SubmitInfo submitInfo;
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitDstStageMask = waitStages.data();
submitInfo.pWaitSemaphores = waitSemaphores.data();
submitInfo.commandBufferCount = static_cast<uint32_t>(cmdBuffers.size());
submitInfo.pCommandBuffers = cmdBuffers.data();
const std::array<vk::Semaphore, 1> signalSemaphores = {m_renderingFinishedSemaphore.get()};
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores.data();
m_graphicsQueue.submit(submitInfo, m_frameInFlightFence.get());
// This frame is now officially in flight
m_inFlight = true;
vk::PresentInfoKHR presentInfo;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores.data();
const std::array<vk::SwapchainKHR, 1> swapChains = {m_swapChain};
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapChains.data();
presentInfo.pImageIndices = &m_swapChainIdx;
presentInfo.pResults = nullptr;
m_presentQueue.presentKHR(presentInfo);
}
} // namespace vulkan
} // namespace graphics
|