Refactored main function to use a singleton patten
This commit is contained in:
parent
29599e4b9a
commit
db832a7dae
@ -18,7 +18,6 @@ namespace DeviceControl {
|
||||
VkPhysicalDeviceProperties deviceProperties;
|
||||
VkPhysicalDeviceFeatures deviceFeatures;
|
||||
|
||||
|
||||
std::vector<VkImage> swapChainImages;
|
||||
VkFormat swapChainImageFormat;
|
||||
VkExtent2D swapChainExtent;
|
||||
@ -298,6 +297,7 @@ namespace DeviceControl {
|
||||
vkDestroySwapchainKHR(Global::device, Global::swapChain, nullptr);
|
||||
if(Global::enableValidationLayers) std::cout << "Destroyed Swap Chain safely\n" << std::endl;
|
||||
}
|
||||
|
||||
void devicelibrary::createImageViews() {
|
||||
swapChainImageViews.resize(swapChainImages.size());
|
||||
for(size_t i = 0; i < swapChainImages.size(); i++) {
|
||||
@ -332,7 +332,6 @@ namespace DeviceControl {
|
||||
}
|
||||
if(Global::enableValidationLayers) std::cout << "Image destroyed safely\n" << std::endl;
|
||||
}
|
||||
|
||||
// --------------------------------------- Getters & Setters ------------------------------------------ //
|
||||
VkFormat devicelibrary::getImageFormat() {
|
||||
return swapChainImageFormat;
|
||||
@ -340,6 +339,7 @@ namespace DeviceControl {
|
||||
std::vector<VkImageView> devicelibrary::getSwapChainImageViews() {
|
||||
return swapChainImageViews;
|
||||
}
|
||||
|
||||
VkExtent2D devicelibrary::getSwapChainExtent() {
|
||||
return swapChainExtent;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "global.h"
|
||||
#include <optional>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
namespace DeviceControl {
|
||||
class devicelibrary {
|
||||
public:
|
||||
@ -19,6 +20,7 @@ class devicelibrary {
|
||||
VkFormat getImageFormat();
|
||||
std::vector<VkImageView> getSwapChainImageViews();
|
||||
VkExtent2D getSwapChainExtent();
|
||||
std::vector<VkFramebuffer> getSwapChainFramebuffers();
|
||||
};
|
||||
}
|
||||
|
||||
|
119
src/entrypoint.cpp
Normal file
119
src/entrypoint.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
#include "entrypoint.h"
|
||||
DeviceControl::devicelibrary deviceLibs;
|
||||
Debug::vulkandebuglibs debugController;
|
||||
Graphics::graphicspipeline graphicsPipeline;
|
||||
RenderPresent::render renderPresentation;
|
||||
VkInstance vulkaninstance;
|
||||
|
||||
|
||||
void EntryApp::setFramebufferResized(bool setter) {
|
||||
framebufferResized = setter;
|
||||
}
|
||||
bool EntryApp::getFramebufferResized() const {
|
||||
return framebufferResized;
|
||||
}
|
||||
static void framebufferResizeCallback(GLFWwindow* window, int width, int height) {
|
||||
auto app = reinterpret_cast<EntryApp*>(glfwGetWindowUserPointer(window));
|
||||
app->EntryApp::getInstance().setFramebufferResized(true);
|
||||
}
|
||||
// Initialize GLFW Window. First, Initialize GLFW lib, disable resizing for
|
||||
// now, and create window.
|
||||
void initWindow() {
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||
|
||||
// Settings for the window are set, create window reference.
|
||||
Global::window = glfwCreateWindow(Global::WIDTH, Global::HEIGHT, "Vulkan", nullptr, nullptr);
|
||||
glfwSetWindowUserPointer(Global::window, &EntryApp::getInstance());
|
||||
glfwSetFramebufferSizeCallback(Global::window, framebufferResizeCallback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void createInstance() {
|
||||
debugController.checkUnavailableValidationLayers(); // Check if there is a mistake with our Validation Layers.
|
||||
|
||||
// Set application info for the vulkan instance!
|
||||
VkApplicationInfo appInfo{};
|
||||
|
||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; // Tell vulkan that appInfo is a Application Info structure
|
||||
appInfo.pApplicationName = "Triangle Test"; // Give the struct a name to use
|
||||
appInfo.applicationVersion = VK_MAKE_VERSION(1,0,0); // Create a Major Minor Patch version number for the application!
|
||||
appInfo.pEngineName = "Agnosia Engine"; // Give an internal name for the engine running
|
||||
appInfo.engineVersion = VK_MAKE_VERSION(1,0,0); // Similar to the App version, give vulkan an *engine* version
|
||||
appInfo.apiVersion = VK_API_VERSION_1_1; // Tell vulkan what the highest API version we will allow this program to run on
|
||||
|
||||
VkInstanceCreateInfo createInfo{}; // Define parameters of new vulkan instance
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; // Tell vulkan this is a info structure
|
||||
createInfo.pApplicationInfo = &appInfo; // We just created a new appInfo structure, so we pass the pointer to it.
|
||||
|
||||
debugController.vulkanDebugSetup(createInfo, vulkaninstance); // Handoff to the debug library to wrap the validation libs in! (And set the window up!)
|
||||
}
|
||||
|
||||
|
||||
void initVulkan() {
|
||||
createInstance();
|
||||
debugController.setupDebugMessenger(vulkaninstance); // The debug messenger is out holy grail, it gives us Vulkan related debug info when built with the -DNDEBUG flag (as per the makefile)
|
||||
deviceLibs.createSurface(vulkaninstance, Global::window);
|
||||
deviceLibs.pickPhysicalDevice(vulkaninstance);
|
||||
deviceLibs.createLogicalDevice();
|
||||
deviceLibs.createSwapChain(Global::window);
|
||||
deviceLibs.createImageViews();
|
||||
graphicsPipeline.createRenderPass();
|
||||
graphicsPipeline.createGraphicsPipeline();
|
||||
graphicsPipeline.createFramebuffers();
|
||||
graphicsPipeline.createCommandPool();
|
||||
graphicsPipeline.createCommandBuffer();
|
||||
renderPresentation.createSyncObject();
|
||||
}
|
||||
|
||||
void mainLoop() { // This loop just updates the GLFW window.
|
||||
while (!glfwWindowShouldClose(Global::window)) {
|
||||
glfwPollEvents();
|
||||
renderPresentation.drawFrame();
|
||||
}
|
||||
vkDeviceWaitIdle(Global::device);
|
||||
}
|
||||
|
||||
void cleanup() { // Similar to the last handoff, destroy the utils in a safe manner in the library!
|
||||
renderPresentation.cleanupSwapChain();
|
||||
graphicsPipeline.destroyGraphicsPipeline();
|
||||
graphicsPipeline.destroyRenderPass();
|
||||
renderPresentation.destroyFenceSemaphores();
|
||||
graphicsPipeline.destroyCommandPool();
|
||||
|
||||
deviceLibs.destroyImageViews();
|
||||
deviceLibs.destroySwapChain();
|
||||
|
||||
vkDestroyDevice(Global::device, nullptr);
|
||||
if(Global::enableValidationLayers) {
|
||||
debugController.DestroyDebugUtilsMessengerEXT(vulkaninstance, nullptr);
|
||||
}
|
||||
|
||||
deviceLibs.destroySurface(vulkaninstance);
|
||||
vkDestroyInstance(vulkaninstance, nullptr);
|
||||
glfwDestroyWindow(Global::window);
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
EntryApp& EntryApp::getInstance() {
|
||||
static EntryApp instance;
|
||||
return instance;
|
||||
}
|
||||
EntryApp::EntryApp() : initialized(false), framebufferResized(false) {}
|
||||
|
||||
void EntryApp::initialize() {
|
||||
initialized = true;
|
||||
}
|
||||
bool EntryApp::isInitialized() const {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void EntryApp::run() {
|
||||
initWindow();
|
||||
initVulkan();
|
||||
mainLoop();
|
||||
cleanup();
|
||||
}
|
||||
|
24
src/entrypoint.h
Normal file
24
src/entrypoint.h
Normal file
@ -0,0 +1,24 @@
|
||||
#include <cstdlib>
|
||||
#include "devicelibrary.h" // Device Library includes global, redundant to include with it here
|
||||
#include "debug/vulkandebuglibs.h"
|
||||
#include "graphics/graphicspipeline.h"
|
||||
#include "graphics/render.h"
|
||||
class EntryApp {
|
||||
public:
|
||||
static EntryApp& getInstance();
|
||||
void initialize();
|
||||
bool isInitialized() const;
|
||||
void run();
|
||||
void setFramebufferResized(bool frame);
|
||||
bool getFramebufferResized() const;
|
||||
private:
|
||||
EntryApp();
|
||||
|
||||
EntryApp(const EntryApp&) = delete;
|
||||
void operator=(const EntryApp&) = delete;
|
||||
|
||||
bool framebufferResized;
|
||||
bool initialized;
|
||||
|
||||
|
||||
};
|
@ -1,5 +1,6 @@
|
||||
#include "global.h"
|
||||
#include "devicelibrary.h"
|
||||
#include <vulkan/vulkan_core.h>
|
||||
namespace Global {
|
||||
|
||||
const std::vector<const char*> validationLayers = {
|
||||
@ -11,14 +12,16 @@ namespace Global {
|
||||
const bool enableValidationLayers = false;
|
||||
#endif
|
||||
|
||||
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
||||
VkDevice device = VK_NULL_HANDLE;
|
||||
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
|
||||
VkSwapchainKHR swapChain = VK_NULL_HANDLE;
|
||||
VkCommandPool commandPool = VK_NULL_HANDLE;
|
||||
VkSurfaceKHR surface;
|
||||
VkDevice device;
|
||||
VkPhysicalDevice physicalDevice;
|
||||
VkSwapchainKHR swapChain;
|
||||
VkCommandPool commandPool;
|
||||
std::vector<VkCommandBuffer> commandBuffers;
|
||||
VkQueue graphicsQueue = VK_NULL_HANDLE;
|
||||
VkQueue presentQueue = VK_NULL_HANDLE;
|
||||
VkQueue graphicsQueue;
|
||||
VkQueue presentQueue;
|
||||
GLFWwindow* window;
|
||||
|
||||
Global::QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) {
|
||||
// First we feed in a integer we want to use to hold the number of queued items, that fills it, then we create that amount of default constructed *VkQueueFamilyProperties* structs.
|
||||
// These store the flags, the amount of queued items in the family, and timestamp data. Queue families are simply group collections of tasks we want to get done.
|
||||
|
@ -19,6 +19,11 @@ namespace Global {
|
||||
extern VkQueue graphicsQueue;
|
||||
extern VkQueue presentQueue;
|
||||
const int MAX_FRAMES_IN_FLIGHT = 2;
|
||||
extern GLFWwindow* window;
|
||||
|
||||
const uint32_t WIDTH = 800;
|
||||
const uint32_t HEIGHT = 600;
|
||||
|
||||
struct QueueFamilyIndices {
|
||||
// We need to check that the Queue families support graphics operations and window presentation, sometimes they can support one or the other,
|
||||
// therefore, we take into account both for completion.
|
||||
|
@ -9,7 +9,6 @@ namespace Graphics {
|
||||
VK_DYNAMIC_STATE_VIEWPORT,
|
||||
VK_DYNAMIC_STATE_SCISSOR
|
||||
};
|
||||
std::vector<VkFramebuffer> swapChainFramebuffers;
|
||||
|
||||
|
||||
VkRenderPass renderPass;
|
||||
@ -17,6 +16,8 @@ namespace Graphics {
|
||||
VkPipeline graphicsPipeline;
|
||||
DeviceControl::devicelibrary deviceLibs;
|
||||
|
||||
std::vector<VkFramebuffer> swapChainFramebuffers;
|
||||
|
||||
static std::vector<char> readFile(const std::string& filename) {
|
||||
std::ifstream file(filename, std::ios::ate | std::ios::binary);
|
||||
if (!file.is_open()) {
|
||||
@ -233,12 +234,6 @@ namespace Graphics {
|
||||
}
|
||||
}
|
||||
}
|
||||
void graphicspipeline::destroyFramebuffers() {
|
||||
for (auto framebuffer : swapChainFramebuffers) {
|
||||
vkDestroyFramebuffer(Global::device, framebuffer, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void graphicspipeline::createCommandPool() {
|
||||
|
||||
Global::QueueFamilyIndices queueFamilyIndices = Global::findQueueFamilies(Global::physicalDevice);
|
||||
@ -319,4 +314,7 @@ namespace Graphics {
|
||||
throw std::runtime_error("failed to record command buffer!");
|
||||
}
|
||||
}
|
||||
std::vector<VkFramebuffer> graphicspipeline::getSwapChainFramebuffers() {
|
||||
return swapChainFramebuffers;
|
||||
}
|
||||
}
|
||||
|
@ -14,5 +14,6 @@ namespace Graphics {
|
||||
void destroyCommandPool();
|
||||
void createCommandBuffer();
|
||||
void recordCommandBuffer(VkCommandBuffer cmndBuffer, uint32_t imageIndex);
|
||||
std::vector<VkFramebuffer> getSwapChainFramebuffers();
|
||||
};
|
||||
}
|
||||
|
@ -1,12 +1,31 @@
|
||||
#include "render.h"
|
||||
#include "graphicspipeline.h"
|
||||
#include "../devicelibrary.h"
|
||||
#include "../entrypoint.h"
|
||||
namespace RenderPresent {
|
||||
|
||||
std::vector<VkSemaphore> imageAvailableSemaphores;
|
||||
std::vector<VkSemaphore> renderFinishedSemaphores;
|
||||
std::vector<VkFence> inFlightFences;
|
||||
Graphics::graphicspipeline pipeline;
|
||||
DeviceControl::devicelibrary deviceLibs;
|
||||
uint32_t currentFrame = 0;
|
||||
|
||||
void recreateSwapChain() {
|
||||
vkDeviceWaitIdle(Global::device);
|
||||
// Don't really wanna do this but I also don't want to create an extra class instance just to call the cleanup function.
|
||||
for(auto framebuffer : pipeline.getSwapChainFramebuffers()) {
|
||||
vkDestroyFramebuffer(Global::device, framebuffer, nullptr);
|
||||
}
|
||||
for(auto imageView : deviceLibs.getSwapChainImageViews()) {
|
||||
vkDestroyImageView(Global::device, imageView, nullptr);
|
||||
}
|
||||
vkDestroySwapchainKHR(Global::device, Global::swapChain, nullptr);
|
||||
|
||||
deviceLibs.createSwapChain(Global::window);
|
||||
deviceLibs.createImageViews();
|
||||
pipeline.createFramebuffers();
|
||||
}
|
||||
// At a high level, rendering in Vulkan consists of 5 steps:
|
||||
// Wait for the previous frame, acquire a image from the swap chain
|
||||
// record a comman d buffer which draws the scene onto that image
|
||||
@ -17,7 +36,14 @@ namespace RenderPresent {
|
||||
vkResetFences(Global::device, 1, &inFlightFences[currentFrame]);
|
||||
|
||||
uint32_t imageIndex;
|
||||
vkAcquireNextImageKHR(Global::device, Global::swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
|
||||
VkResult result = vkAcquireNextImageKHR(Global::device, Global::swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);
|
||||
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||
recreateSwapChain();
|
||||
return;
|
||||
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
|
||||
throw std::runtime_error("failed to acquire swap chain image!");
|
||||
}
|
||||
vkResetFences(Global::device, 1, &inFlightFences[currentFrame]);
|
||||
|
||||
vkResetCommandBuffer(Global::commandBuffers[currentFrame], /*VkCommandBufferResetFlagBits*/ 0);
|
||||
pipeline.recordCommandBuffer(Global::commandBuffers[currentFrame], imageIndex);
|
||||
@ -54,7 +80,13 @@ namespace RenderPresent {
|
||||
|
||||
presentInfo.pImageIndices = &imageIndex;
|
||||
|
||||
vkQueuePresentKHR(Global::presentQueue, &presentInfo);
|
||||
result = vkQueuePresentKHR(Global::presentQueue, &presentInfo);
|
||||
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || EntryApp::getInstance().getFramebufferResized()) {
|
||||
EntryApp::getInstance().setFramebufferResized(false);
|
||||
recreateSwapChain();
|
||||
} else if (result != VK_SUCCESS) {
|
||||
throw std::runtime_error("failed to present swap chain image!");
|
||||
}
|
||||
currentFrame = (currentFrame + 1) % Global::MAX_FRAMES_IN_FLIGHT;
|
||||
}
|
||||
#pragma info
|
||||
@ -70,7 +102,8 @@ namespace RenderPresent {
|
||||
// enqueue QueueOne, Signal semaphore when done, start now.
|
||||
// vkQueueSubmit(work: QueueOne, signal: semaphore, wait: none)
|
||||
// enqueue QueueTwo, wait on semaphore to start
|
||||
// vkQueueSubmit(work: QueueTwo, signal: None, wait: semaphore)
|
||||
// vkQueueSubmit(
|
||||
// work: QueueTwo, signal: None, wait: semaphore)
|
||||
// FENCES
|
||||
// Fences are basically semaphores for the CPU! Otherwise known as the host. If the host needs to know when the GPU has finished a task, we use a fence.
|
||||
// VkCommandBuffer cmndBuf = ...
|
||||
@ -103,11 +136,21 @@ namespace RenderPresent {
|
||||
|
||||
|
||||
}
|
||||
void destroyFenceSemaphore() {
|
||||
void render::destroyFenceSemaphores() {
|
||||
for (size_t i = 0; i < Global::MAX_FRAMES_IN_FLIGHT; i++) {
|
||||
vkDestroySemaphore(Global::device, imageAvailableSemaphores[i], nullptr);
|
||||
vkDestroySemaphore(Global::device, renderFinishedSemaphores[i], nullptr);
|
||||
vkDestroyFence(Global::device, inFlightFences[i], nullptr);
|
||||
}
|
||||
}
|
||||
void render::cleanupSwapChain() {
|
||||
for(auto framebuffer : pipeline.getSwapChainFramebuffers()) {
|
||||
vkDestroyFramebuffer(Global::device, framebuffer, nullptr);
|
||||
}
|
||||
for(auto imageView : deviceLibs.getSwapChainImageViews()) {
|
||||
vkDestroyImageView(Global::device, imageView, nullptr);
|
||||
}
|
||||
vkDestroySwapchainKHR(Global::device, Global::swapChain, nullptr);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,5 +7,7 @@ class render {
|
||||
public:
|
||||
void drawFrame();
|
||||
void createSyncObject();
|
||||
void destroyFenceSemaphores();
|
||||
void cleanupSwapChain();
|
||||
};
|
||||
}
|
||||
|
111
src/main.cpp
111
src/main.cpp
@ -1,114 +1,9 @@
|
||||
#include "devicelibrary.h" // Device Library includes global, redundant to include with it here
|
||||
#include "debug/vulkandebuglibs.h"
|
||||
#include "graphics/graphicspipeline.h"
|
||||
#include "graphics/render.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
const uint32_t WIDTH = 800;
|
||||
const uint32_t HEIGHT = 600;
|
||||
|
||||
// Define a base class structure to handle public and private methods
|
||||
class TriangleTestApplication {
|
||||
|
||||
public:
|
||||
void run() {
|
||||
initWindow();
|
||||
initVulkan();
|
||||
mainLoop();
|
||||
cleanup();
|
||||
}
|
||||
|
||||
private:
|
||||
DeviceControl::devicelibrary deviceLibs;
|
||||
Debug::vulkandebuglibs debugController;
|
||||
Graphics::graphicspipeline graphicsPipeline;
|
||||
RenderPresent::render renderPresentation;
|
||||
GLFWwindow* window;
|
||||
VkInstance instance;
|
||||
|
||||
// Initialize GLFW Window. First, Initialize GLFW lib, disable resizing for
|
||||
// now, and create window.
|
||||
void initWindow() {
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||
|
||||
// Settings for the window are set, create window reference.
|
||||
window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
|
||||
}
|
||||
|
||||
void initVulkan() {
|
||||
createInstance();
|
||||
debugController.setupDebugMessenger(instance); // The debug messenger is out holy grail, it gives us Vulkan related debug info when built with the -DNDEBUG flag (as per the makefile)
|
||||
deviceLibs.createSurface(instance, window);
|
||||
deviceLibs.pickPhysicalDevice(instance);
|
||||
deviceLibs.createLogicalDevice();
|
||||
deviceLibs.createSwapChain(window);
|
||||
deviceLibs.createImageViews();
|
||||
graphicsPipeline.createRenderPass();
|
||||
graphicsPipeline.createGraphicsPipeline();
|
||||
graphicsPipeline.createFramebuffers();
|
||||
graphicsPipeline.createCommandPool();
|
||||
graphicsPipeline.createCommandBuffer();
|
||||
renderPresentation.createSyncObject();
|
||||
}
|
||||
|
||||
void createInstance() {
|
||||
debugController.checkUnavailableValidationLayers(); // Check if there is a mistake with our Validation Layers.
|
||||
|
||||
// Set application info for the vulkan instance!
|
||||
VkApplicationInfo appInfo{};
|
||||
|
||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; // Tell vulkan that appInfo is a Application Info structure
|
||||
appInfo.pApplicationName = "Triangle Test"; // Give the struct a name to use
|
||||
appInfo.applicationVersion = VK_MAKE_VERSION(1,0,0); // Create a Major Minor Patch version number for the application!
|
||||
appInfo.pEngineName = "Agnosia Engine"; // Give an internal name for the engine running
|
||||
appInfo.engineVersion = VK_MAKE_VERSION(1,0,0); // Similar to the App version, give vulkan an *engine* version
|
||||
appInfo.apiVersion = VK_API_VERSION_1_1; // Tell vulkan what the highest API version we will allow this program to run on
|
||||
|
||||
VkInstanceCreateInfo createInfo{}; // Define parameters of new vulkan instance
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; // Tell vulkan this is a info structure
|
||||
createInfo.pApplicationInfo = &appInfo; // We just created a new appInfo structure, so we pass the pointer to it.
|
||||
|
||||
debugController.vulkanDebugSetup(createInfo, instance); // Handoff to the debug library to wrap the validation libs in! (And set the window up!)
|
||||
}
|
||||
|
||||
void mainLoop() { // This loop just updates the GLFW window.
|
||||
while (!glfwWindowShouldClose(window)) {
|
||||
glfwPollEvents();
|
||||
renderPresentation.drawFrame();
|
||||
}
|
||||
vkDeviceWaitIdle(Global::device);
|
||||
}
|
||||
|
||||
void cleanup() { // Similar to the last handoff, destroy the utils in a safe manner in the library!
|
||||
graphicsPipeline.destroyCommandPool();
|
||||
graphicsPipeline.destroyFramebuffers();
|
||||
graphicsPipeline.destroyGraphicsPipeline();
|
||||
graphicsPipeline.destroyRenderPass();
|
||||
deviceLibs.destroyImageViews();
|
||||
deviceLibs.destroySwapChain();
|
||||
vkDestroyDevice(Global::device, nullptr);
|
||||
if(Global::enableValidationLayers) {
|
||||
debugController.DestroyDebugUtilsMessengerEXT(instance, nullptr);
|
||||
}
|
||||
|
||||
deviceLibs.destroySurface(instance);
|
||||
vkDestroyInstance(instance, nullptr);
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
}
|
||||
};
|
||||
|
||||
#include "entrypoint.h"
|
||||
int main() {
|
||||
TriangleTestApplication app;
|
||||
EntryApp::getInstance().initialize();
|
||||
|
||||
try {
|
||||
app.run();
|
||||
EntryApp::getInstance().run();
|
||||
} catch (const std::exception &e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
|
Loading…
Reference in New Issue
Block a user