Project
This commit is contained in:
+136
@@ -0,0 +1,136 @@
|
||||
#include "app.h"
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include "vulkan/vulkan.hpp"
|
||||
|
||||
void Application::run() {
|
||||
initWindow();
|
||||
initVulkan();
|
||||
mainLoop();
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void Application::initVulkan() {
|
||||
createInstance();
|
||||
setupDebugMessenger();
|
||||
createSurface();
|
||||
pickPhysicalDevice();
|
||||
createLogicalDevice();
|
||||
createSwapChain();
|
||||
createImageViews();
|
||||
createGraphicsPipeline();
|
||||
createCommandPool();
|
||||
createCommandBuffer();
|
||||
createSyncObjects();
|
||||
}
|
||||
|
||||
void Application::mainLoop() {
|
||||
// Loop until the window should be closed
|
||||
while (!glfwWindowShouldClose(m_window)) {
|
||||
// Poll for new window events
|
||||
glfwPollEvents();
|
||||
// Draw the next frame
|
||||
drawFrame();
|
||||
}
|
||||
|
||||
// Once the window is closed, its time to clean up everything. Which once we are out of this function GPU objects
|
||||
// are de-allocated Since there is a high chance the GPU is still working on stuff, we need to wait for the device
|
||||
// to idle before we return.
|
||||
m_device.waitIdle();
|
||||
}
|
||||
|
||||
void Application::drawFrame() {
|
||||
// Wait for the previous frame to end
|
||||
auto fenceResult = m_device.waitForFences(*m_inFlightFences[m_frameIndex], vk::True, UINT64_MAX);
|
||||
// Get the next image in the swapchain
|
||||
auto [result, imageIndex] =
|
||||
m_swapchain.acquireNextImage(UINT64_MAX, *m_presentCompleteSemaphores[m_frameIndex], nullptr);
|
||||
|
||||
// Check to make sure the swapchain didn't report an eErrorOutOfDateKHR error
|
||||
if (result == vk::Result::eErrorOutOfDateKHR) {
|
||||
// Recreate the swapchain
|
||||
recreateSwapchain();
|
||||
return;
|
||||
}
|
||||
|
||||
// If the result isn't a eSuccess or eSuboptimalKHR, something has gone wrong and we should report on it.
|
||||
if (result != vk::Result::eSuccess && result != vk::Result::eSuboptimalKHR) {
|
||||
throw std::runtime_error("Failed to acquire next swapchain image");
|
||||
}
|
||||
|
||||
// Reset the fence of the current image
|
||||
m_device.resetFences(*m_inFlightFences[m_frameIndex]);
|
||||
|
||||
// Record the command buffer
|
||||
recordCommandBuffer(imageIndex);
|
||||
|
||||
// Submit the command buffer to the queue
|
||||
vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput);
|
||||
const vk::SubmitInfo submitInfo{// Wait for the current frames present semaphore
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &*m_presentCompleteSemaphores[m_frameIndex],
|
||||
// Set our destination
|
||||
.pWaitDstStageMask = &waitDestinationStageMask,
|
||||
// Pass the command buffer/s to submit
|
||||
.commandBufferCount = 1,
|
||||
.pCommandBuffers = &*m_commandBuffers[m_frameIndex],
|
||||
// Pass the rendering semaphore to signal when done
|
||||
.signalSemaphoreCount = 1,
|
||||
.pSignalSemaphores = &*m_renderFinishedSemaphores[imageIndex]};
|
||||
|
||||
// Submit to the graphics queue
|
||||
m_queue.submit(submitInfo, *m_inFlightFences[m_frameIndex]);
|
||||
|
||||
|
||||
// Present the image
|
||||
try {
|
||||
const vk::PresentInfoKHR presentInfo{
|
||||
// Wait for the rendering semaphore
|
||||
.waitSemaphoreCount = 1,
|
||||
.pWaitSemaphores = &*m_renderFinishedSemaphores[imageIndex],
|
||||
// Pass the swapchain we want to present with
|
||||
.swapchainCount = 1,
|
||||
.pSwapchains = &*m_swapchain,
|
||||
// Pass the imageIndex of image we want to present in the swapchain
|
||||
.pImageIndices = &imageIndex,
|
||||
.pResults = nullptr // Optional, allows you to specify an array of vk::Result values to check for every
|
||||
// swapchain. We only have one so we can just use the vk::Result returned from the
|
||||
// present function
|
||||
};
|
||||
result = m_queue.presentKHR(presentInfo);
|
||||
|
||||
// If the result is eErrorOutOfDateKHR || eSuboptimalKHR || if the windows framebuffer has been resized we need
|
||||
// to recreate the swapchain
|
||||
if (result == vk::Result::eErrorOutOfDateKHR || result == vk::Result::eSuboptimalKHR || m_framebufferResized) {
|
||||
m_framebufferResized = false;
|
||||
recreateSwapchain();
|
||||
} else if (result != vk::Result::eSuccess) {
|
||||
// If we get any other error, we should error out
|
||||
throw std::runtime_error("Failed to present swapchain image");
|
||||
}
|
||||
} catch (const vk::SystemError &e) {
|
||||
// There is a chance that a SystemError will be thrown when presenting. The SystemError.code() could also be a
|
||||
// eErrorOutOfDateKHR as well, so that should also be checked for so we can just recreate the swapchain as
|
||||
// normal. All other errors should crash out.
|
||||
if (e.code().value() == static_cast<int>(vk::Result::eErrorOutOfDateKHR)) {
|
||||
recreateSwapchain();
|
||||
} else {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// Rotate the frame index
|
||||
m_frameIndex = (m_frameIndex + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||
}
|
||||
|
||||
void Application::cleanup() {
|
||||
// Destroy the swapchain
|
||||
cleanupSwapchain();
|
||||
|
||||
// Destroy the window
|
||||
glfwDestroyWindow(m_window);
|
||||
// Terminate GLFW
|
||||
glfwTerminate();
|
||||
}
|
||||
Reference in New Issue
Block a user